বাশের রিড-এ-ফাইল কমান্ড সাবস্টিটিউশন বোঝা


11

নীচের লাইনে বাশ ঠিক কীভাবে আচরণ করে তা বোঝার চেষ্টা করছি:

$(< "$FILE")

বাশ ম্যান পৃষ্ঠা অনুসারে, এটি সমান:

$(cat "$FILE")

এবং আমি এই দ্বিতীয় লাইনের জন্য যুক্তিটির রেখাটি অনুসরণ করতে পারি। ব্যাশ সঞ্চালিত উপর পরিবর্তনশীল সম্প্রসারণ $FILE, কমান্ড প্রতিকল্পন প্রবেশ করে, এর মান পাস $FILEকরার cat, বিড়াল বিষয়বস্তু আউটপুট $FILEমান আউটপুট কমান্ড ভিতরে ফলে সঙ্গে সমগ্র লাইন প্রতিস্থাপন মানক আউটপুটে, কমান্ড প্রতিকল্পন শেষ, এবং মত চালানো ব্যাশ প্রচেষ্টা একটি সাধারণ আদেশ।

তবে, আমি উপরে উল্লিখিত প্রথম লাইনের জন্য, আমি এটিকে বুঝতে পারি: বাশ স্ট্যান্ডার্ড ইনপুট পড়ার জন্য $FILEব্যাশ চালু $FILEকরে, কোনওভাবে স্ট্যান্ডার্ড ইনপুটটি স্ট্যান্ডার্ড আউটপুটে অনুলিপি করা হয় , কমান্ড প্রতিস্থাপন শেষ হয় এবং বাশ ফলস্বরূপ মান কার্যকর করার চেষ্টা করে আউটপুট।

কেউ দয়া করে আমাকে ব্যাখ্যা করতে পারেন কীভাবে $FILEস্ট্যান্ডিন থেকে স্টডআউটে যায়?

উত্তর:


-3

<সরাসরি একটি দৃষ্টিভঙ্গি নয় ব্যাশ কমান্ড প্রতিকল্পন । এটি একটি পুনর্নির্দেশ অপারেটর (পাইপের মতো) যা কিছু শেল একটি আদেশ ছাড়াই অনুমতি দেয় (POSIX এই আচরণটি নির্দিষ্ট করে না)।

সম্ভবত এটি আরও স্পেস সহ আরও স্পষ্ট হবে:

echo $( < $FILE )

এটি কার্যকরভাবে আরও পসিক্স-নিরাপদ হিসাবে একই

echo $( cat $FILE )

... যা কার্যকরভাবে *

echo $( cat < $FILE )

আসুন শেষ সংস্করণ দিয়ে শুরু করা যাক। এটি catকোনও যুক্তি ছাড়াই চলে , যার অর্থ এটি স্ট্যান্ডার্ড ইনপুট থেকে পড়বে। $FILEএর কারণে স্ট্যান্ডার্ড ইনপুটগুলিতে পুনঃনির্দেশিত হয় <, সুতরাং catএর সামগ্রীগুলি স্ট্যান্ডার্ড আউটপুটে রাখে। $(command)Subsitution তারপর পাহাড় জমে catজন্য আর্গুমেন্ট মধ্যে এর আউটপুট echo

ইন bash(তবে পসিক্স স্ট্যান্ডার্ডে নেই), আপনি <কোনও আদেশ ছাড়াই ব্যবহার করতে পারেন । bash(এবং zshএবং kshনা কিন্তু dash) ব্যাখ্যা করবে যেন cat <, যদিও একটি নতুন subprocess invoking ছাড়া। এই শেল নেটিভ হিসাবে, এটি দ্রুত আক্ষরিক বহিরাগত কমান্ড চালানোর চেয়ে cat* এই কারণেই আমি বলি "কার্যকরভাবে একইভাবে" "


সুতরাং সর্বশেষ অনুচ্ছেদে আপনি যখন " bashএটি ব্যাখ্যা করবেন " বলছেন cat filename, আপনার অর্থ কি এই আচরণটি প্রতিস্থাপনের আদেশের জন্য নির্দিষ্ট? কারণ আমি যদি < filenameনিজেই চালনা করি তবে ব্যাশ তা কার্যকর করে না। এটি কিছুই না আউটপুট এবং একটি প্রম্পটে আমাকে ফিরিয়ে দেবে।
স্ট্যানলি ইউ

একটি কমান্ড এখনও প্রয়োজন। @cuonglm থেকে আমার মূল টেক্সট রদবদল cat < filenameকরতে cat filenameযা আমি বিরোধিতা এবং ফেরান পারে।
অ্যাডাম কাটজ

1
পাইপ হ'ল এক ধরণের ফাইল। শেল অপারেটর |দুটি সাবপ্রসেসের মধ্যে একটি পাইপ তৈরি করে (বা কিছু শেল দিয়ে শেল এর স্ট্যান্ডার্ড ইনপুট পর্যন্ত) pro শেল অপারেটর $(…)শেল নিজেই একটি সাবপ্রসেস থেকে পাইপ তৈরি করে (তার স্ট্যান্ডার্ড ইনপুটটিতে নয়)। শেল অপারেটর <একটি পাইপ জড়িত না, এটি কেবল একটি ফাইল খোলে এবং ফাইল বর্ণনাকারীকে স্ট্যান্ডার্ড ইনপুট এ নিয়ে যায়।
গিলস 23'15

3
< fileযেমনটি হয় না cat < file( zshযেখানে এটি পছন্দ হয় তা বাদে $READNULLCMD < file)। < fileনিখুঁতভাবে পসিক্স এবং কেবল fileপড়ার জন্য খোলে এবং তারপরে কিছুই হয় না (তাই fileসরাসরি চলে আসা)। এটা $(< file)বা `< file`যে একটি বিশেষ অপারেটর ksh, zshএবং bash(এবং আচরণ POSIX মধ্যে অনির্দিষ্ট রাখা)। বিস্তারিত জানার জন্য আমার উত্তর দেখুন ।
স্টাফেন চেজেলাস

2
@ স্টাফেনচাজেলাসের মন্তব্যটিকে অন্য একটি আলোকে রাখার জন্য: প্রথম অনুমানের মতো, $(cmd1) $(cmd2)সাধারণত একই রকম হবে $(cmd1; cmd2)। তবে কেসটি কোথায় cmd2তা দেখুন < file। যদি আমরা বলি $(cmd1; < file), ফাইলটি পড়া হয় না, তবে, সাথে $(cmd1) $(< file)থাকে। সুতরাং এটি বলা ভুল যে $(< file)এটি কেবল $(command)একটি কমান্ডের সাথে একটি সাধারণ ঘটনা < file।   কমান্ড প্রতিস্থাপনের $(< …)একটি বিশেষ ক্ষেত্রে , এবং পুনঃনির্দেশের সাধারণ ব্যবহার নয়।
স্কট

14

$(<file)(এছাড়াও এতে কাজ করে `<file`) হ'ল zshএবং দ্বারা অনুলিপি করা কর্ন শেলের একটি বিশেষ অপারেটর bash। এটি দেখতে অনেকটা কমান্ড প্রতিস্থাপনের মতো দেখাচ্ছে তবে এটি বাস্তবে নয়।

পসিক্স শেলগুলিতে একটি সাধারণ কমান্ডটি হ'ল:

< file var1=value1 > file2 cmd 2> file3 args 3> file4

সমস্ত অংশগুলি alচ্ছিক, আপনার কেবল পুনর্নির্দেশ, কেবল আদেশ, কেবলমাত্র অ্যাসাইনমেন্ট বা সংমিশ্রণ থাকতে পারে।

যদি পুনঃনির্দেশগুলি থাকে তবে কোনও আদেশ নেই, পুনর্নির্দেশগুলি সম্পাদন করা হয় (সুতরাং > fileএটি খোলা হবে এবং কাটা হবে file) তবে কিছুই ঘটে না। সুতরাং

< file

fileপড়ার জন্য খোলে , তবে কোনও আদেশ না থাকায় কিছুই ঘটে না। সুতরাং fileতারপর বন্ধ এবং এটি। যদি $(< file)একটি সরল কমান্ড প্রতিস্থাপন হয় , তবে এটি কিছুতেই প্রসারিত হত।

ইন POSIX স্পেসিফিকেশন , ইন $(script), যদি scriptশুধুমাত্র পুনঃনির্দেশগুলি নিয়ে গঠিত, যে অনির্দিষ্ট ফল । এটি কর্ন শেলের সেই বিশেষ আচরণের অনুমতি দেয়।

কেএসএসে (এখানে এটি দিয়ে পরীক্ষা করা হয়েছে ksh93u+), যদি স্ক্রিপ্টটিতে একটি এবং কেবলমাত্র একটি সাধারণ কমান্ড থাকে (যদিও মন্তব্যগুলি আগে এবং পরে অনুমোদিত হয়) কেবলমাত্র পুনর্নির্দেশগুলি নিয়ে গঠিত (কোনও আদেশ নয়, কোনও কার্যনির্বাহী নয়) এবং যদি প্রথম পুনর্নির্দেশটি স্টিডিন (fd) হয় 0) ইনপুট শুধুমাত্র ( <, <<বা <<<) ফেরৎ, তাই:

  • $(< file)
  • $(0< file)
  • $(<&3)(এছাড়াও $(0>&3)বাস্তবে একই অপারেটর কার্যকর হিসাবে)
  • $(< file > foo 2> $(whatever))

কিন্তু না:

  • $(> foo < file)
  • না $(0<> file)
  • না $(< file; sleep 1)
  • না $(< file; < file2)

তারপর

  • প্রথম পুনর্নির্দেশ ছাড়া সমস্ত এড়ানো হবে (সেগুলি পার্স করে দেওয়া হয়)
  • এবং এটি ফাইল / হেরেডোক / হিয়ারস্ট্রিংয়ের সামগ্রীতে প্রসারিত হয় (বা যেমন কিছু ব্যবহার করে ফাইল বর্ণনাকারীর কাছ থেকে যা কিছু পড়তে পারে <&3) বিচ্ছিন্ন নিউলাইন অক্ষরগুলি বিয়োগ করে।

যেন ব্যবহার $(cat < file)ব্যতীত

  • পড়াটি শেল দ্বারা অভ্যন্তরীণভাবে করা হয় এবং দ্বারা হয় না cat
  • কোনও পাইপ বা অতিরিক্ত প্রক্রিয়া জড়িত নয়
  • উপরের ফলস্বরূপ, যেহেতু অভ্যন্তরীণ কোডটি সাবশেলে চালিত হচ্ছে না, তারপরে কোনও পরিবর্তনই পরে থাকে (যেমন $(<${file=foo.txt})বা তেমন $(<file$((++n))))
  • ত্রুটিগুলি পড়ুন (ফাইলগুলি খোলার সময় বা ফাইলের ডুপ্লিকেট করার সময় ত্রুটি না থাকলেও) চুপচাপ উপেক্ষা করা হবে।

ইন zsh, এটা ছাড়া যে বিশেষ আচরণ শুধুমাত্র আলোড়ন আছে যখন শুধুমাত্র একটি ফাইল ইনপুট ফেরৎ হয় একই ( <fileবা 0< file, কোন <&3, <<<here, < a < b...)

তবে, অন্যান্য শেলগুলি অনুকরণ করার সময় বাদে:

< file
<&3
<<< here...

এটি তখন যখন কমান্ড ছাড়াই কেবল ইনপুট পুনর্নির্দেশগুলি থাকে, কমান্ড প্রতিস্থাপনের বাইরে, (ডিফল্ট অনুসারে একটি পেজার) zshচালায় $READNULLCMDএবং যখন ইনপুট এবং আউটপুট পুনঃনির্দেশ উভয়ই থাকে $NULLCMD( catডিফল্টরূপে), তাই $(<&3)বিশেষ হিসাবে স্বীকৃতি না পেলেও অপারেটর, এটি এখনও kshপেজারকে এটি করার জন্য অনুরোধ করার মতো কাজ করবে (যে পেজার catতার স্টাডাউট যেহেতু পাইপ হবে তাই পছন্দ করে) acting

তবে যখন kshএর $(< a < b)বিষয়বস্তুর সাথে প্রসারিত হবে aএ, zsh, এটা বিষয়বস্তুর সাথে বিস্তৃতি aএবং b(বা শুধু bযদি multiosবিকল্প অক্ষম করা হয়েছে), $(< a > b)কপি হবে aথেকে bকিছুই, ইত্যাদি প্রসারিত

bash একই রকম অপারেটর রয়েছে তবে কয়েকটি পার্থক্য সহ:

  • মন্তব্যগুলি আগে অনুমোদিত কিন্তু পরে নয়:

    echo "$(
       # getting the content of file
       < file)"
    

    কাজ করে কিন্তু:

    echo "$(< file
       # getting the content of file
    )"
    

    কিছুই প্রসারিত।

  • যেমন zsh, কেবল একটি ফাইল স্টিডিন পুনঃনির্দেশ, যদিও কোনওটির পিছনে কোনও ফল নেই $READNULLCMD, সুতরাং $(<&3), $(< a < b)পুনঃনির্দেশগুলি সম্পাদন করুন তবে কিছুই প্রসারিত করবেন না।

  • কোনও কারণে, যখন bashপ্রার্থনা না করে cat, এটি এখনও এমন প্রক্রিয়া জোর করে যা পাইপের মাধ্যমে ফাইলের বিষয়বস্তুগুলিকে ফিড দেয় যা এটি অন্যান্য শেলের তুলনায় অপ্টিমাইজেশনের তুলনায় অনেক কম করে তোলে। এটা একটা মত প্রভাব আছে $(cat < file)যেখানে catএকটি builtin হবে cat
  • উপরের ফলস্বরূপ, এর মধ্যে করা কোনও পরিবর্তন পরে নষ্ট হয়ে যায় ( $(<${file=foo.txt})উদাহরণস্বরূপ, উপরে উল্লিখিত, এই $fileকার্যভারটি পরে হারিয়ে যায়)।

ইন bash, IFS= read -rd '' var < file (এছাড়াও এতে কাজ করে zsh) একটি টেক্সট ফাইলের বিষয়বস্তুকে একটি ভেরিয়েবলের মধ্যে পড়ার আরও কার্যকর উপায় । এর পিছনে থাকা নতুন লাইনের চরিত্রগুলি সংরক্ষণ করার সুবিধাও রয়েছে। আরও দেখুন $mapfile[file]মধ্যে zsh(ইন zsh/mapfileমডিউল এবং শুধুমাত্র নিয়মিত ফাইল জন্য) যা বাইনারি ফাইল সঙ্গে কাজ করে।

উল্লেখ্য, পিডিএক্স-ভিত্তিক বৈকল্পিকগুলির kshksh93 এর তুলনায় কয়েকটি ভিন্নতা রয়েছে। আগ্রহের বিষয়, mksh(সেইগুলির মধ্যে পিডিএক্স-উত্পন্ন শেলগুলির মধ্যে একটি), ইন

var=$(<<'EOF'
That's multi-line
test with *all* sorts of "special"
characters
EOF
)

এতে অনুকূলিত হয়েছে যে এখানে নথির বিষয়বস্তু (পিছনের অক্ষরগুলি ছাড়াই) অস্থায়ী ফাইল বা পাইপ ব্যবহার না করে প্রসারিত করা হয়েছে অন্যথায় এখানে নথির ক্ষেত্রে, যা এটি কার্যকর মাল্টি-লাইন উদ্ধৃতি বাক্য গঠন করে তোলে।

সমস্ত সংস্করণে পোর্টেবল হওয়ার জন্য ksh, zshএবং bashসর্বোত্তম হ'ল কেবল $(<file)মন্তব্যগুলি এড়ানো এবং মনে রাখতে হবে যে ভেরিয়েবলগুলির মধ্যে পরিবর্তনগুলি সংরক্ষণ করা যেতে পারে বা সংরক্ষণ করা যায় না।


এটি কি সঠিক যে $(<)ফাইল নামগুলির একটি অপারেটর? Is <মধ্যে $(<)একটি ফেরৎ অপারেটর না, অথবা তার নিজের উপর একটি অপারেটর, এবং সমগ্র অপারেটর এর অংশ হতে হবে $(<)?
টিম

@ টিম, আপনি কীভাবে তাদের কল করতে চান তা বিবেচ্য নয়। একইভাবে একইভাবে $(<file)কন্টেন্ট প্রসারিত বোঝানো হয় । এটি কীভাবে সম্পন্ন হয় তা শেল থেকে শেলের পরিবর্তিত হয় যা উত্তরে দৈর্ঘ্যে বর্ণিত। যদি আপনি চান, আপনি বলতে পারেন যে এটি একটি বিশেষ অপারেটর যা ট্রিগার হয় যখন কমান্ড সাবস্টিটিউশন (সিনট্যাকটিকালি) মতো দেখতে একটি সিঙ্গল স্টিডিন পুনর্নির্দেশের মতো দেখায় (সিনট্যাক্টিক্যালি) থাকে, তবে আবার শ্যাভের উপর নির্ভর করে সতর্কতা এবং তারতম্যের সাথে এখানে তালিকাভুক্ত করা হয় here । file$(cat < file)
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলাস: যথারীতি আকর্ষণীয়; আমি এটি বুকমার্ক করেছি। সুতরাং, n<&mএবং n>&mএকই জিনিস না? আমি এটি জানতাম না, তবে আমার ধারণা এটি খুব অবাক হওয়ার মতো নয়।
স্কট

@ স্কট, হ্যাঁ, তারা দু'জনেই একটি করে dup(m, n)। আমি স্টডিও এবং কিছু ব্যবহার করে ksh86 এর কিছু প্রমাণ দেখতে পাচ্ছি fdopen(fd, "r" or "w"), সুতরাং এটির পরে এটি ম্যাটার হতে পারে। তবে শেলের মধ্যে স্টডিও ব্যবহার করা কিছুটা অর্থপূর্ণ নয়, তাই আমি আশা করি না যে আপনি কোনও আধুনিক শেল পাবেন যেখানে এটি কোনও তাত্পর্য তৈরি করবে। এক পার্থক্য যে >&nহয় dup(n, 1)(সংক্ষেপে 1>&n,) যখন <&nহয় dup(n, 0)(সংক্ষেপে 0<&n)।
স্টাফেন চেজেলাস

ঠিক। অবশ্যই, ফাইল বর্ণনাকারী সদৃশ কলটির দ্বি-যুক্তি ফর্মটি বলা হয় dup2(); dup()কেবলমাত্র একটি যুক্তি নেয় এবং যেমন open(), সর্বনিম্ন উপলব্ধ ফাইল বর্ণনাকারী ব্যবহার করে। (আজ আমি শিখেছি যে একটি dup3()ফাংশন রয়েছে ))
স্কট

8

কারণ bashএটি আপনার জন্য অভ্যন্তরীণভাবে হয় না, ফাইলনামটি বিস্তৃত করে এবং বিড়ালগুলি ফাইলটিকে স্ট্যান্ডার্ড আউটপুটে উন্নীত করে, আপনি যেমন করতেন তবে $(cat < filename)। এটি একটি বাশ বৈশিষ্ট্য, সম্ভবত bashকীভাবে এটি কাজ করে তা জানতে আপনার উত্স কোডটি খতিয়ে দেখার প্রয়োজন ।

এই বৈশিষ্ট্যটি হ্যান্ডেল করার জন্য এখানে ফাংশনটি ( bashউত্স কোড, ফাইল থেকে builtins/evalstring.c):

/* Handle a $( < file ) command substitution.  This expands the filename,
   returning errors as appropriate, then just cats the file to the standard
   output. */
static int
cat_file (r)
     REDIRECT *r;
{
  char *fn;
  int fd, rval;

  if (r->instruction != r_input_direction)
    return -1;

  /* Get the filename. */
  if (posixly_correct && !interactive_shell)
    disallow_filename_globbing++;
  fn = redirection_expand (r->redirectee.filename);
  if (posixly_correct && !interactive_shell)
    disallow_filename_globbing--;

  if (fn == 0)
    {
      redirection_error (r, AMBIGUOUS_REDIRECT);
      return -1;
    }

  fd = open(fn, O_RDONLY);
  if (fd < 0)
    {
      file_error (fn);
      free (fn);
      return -1;
    }

  rval = zcatfd (fd, 1, fn);

  free (fn);
  close (fd);

  return (rval);
}

একটি নোট যা $(<filename)একেবারে সমতুল্য নয় $(cat filename); যদি ফাইলের নামটি ড্যাশ দিয়ে শুরু হয় তবে পরে ব্যর্থ হবে -

$(<filename)মূলতঃ থেকে এসেছিল kshএবং bashএখান থেকে যুক্ত হয়েছিল Bash-2.02


1
cat filenameযদি ফাইলের নামটি ড্যাশ দিয়ে শুরু হয় তবে ব্যর্থ হবে কারণ বিড়াল বিকল্পগুলি গ্রহণ করে। আপনি বেশিরভাগ আধুনিক সিস্টেমে এর সাথে কাজ করতে পারেন cat -- filename
অ্যাডাম কাটজ

-1

কমান্ড প্রতিস্থাপনকে যথারীতি একটি কমান্ড চালানো এবং আউটপুটটি যেখানে আপনি কমান্ডটি চালাচ্ছেন সেটিকে ডাম্পিং হিসাবে ভাবেন।

কমান্ডের আউটপুট অন্য একটি কমান্ডের আর্গুমেন্ট হিসাবে, একটি ভেরিয়েবল সেট করতে এবং এমনকি লুপের জন্য আর্গুমেন্ট তালিকা তৈরি করার জন্য ব্যবহার করা যেতে পারে।

foo=$(echo "bar")ভেরিয়েবলের মান সেট $fooকরে bar; কমান্ডের আউটপুট echo bar

কমান্ড সাবস্টিটিউশন


1
আমি বিশ্বাস করি যে প্রশ্নটি ওপেন কমান্ড প্রতিস্থাপনের মূল বিষয়গুলি বুঝতে পারে তা থেকে মোটামুটি পরিষ্কার; প্রশ্নটি বিশেষ মামলার বিষয়ে $(< file), এবং সাধারণ ক্ষেত্রে তার কোনও টিউটোরিয়াল দরকার নেই। আপনি যদি বলছেন যে কমান্ডের সাথে $(< file)এটি কেবলমাত্র একটি সাধারণ ঘটনা , তবে আপনি আদম কাটজ যে কথা বলছেন একই কথাটি বলছেন , এবং আপনি উভয়ই ভুল। $(command)< file
স্কট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.