آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

جایگزینی فرمان

Command Substitution

جایگزینی فرمان

جایگزینی فرمان یک راهکار بسیار نیرومند پوسته یونیکس است. برای درج خروجی یک فرمان در فرمان دیگر به کار می‌رود. به عنوان مثال، با یک تخصیص:

  $ today=$(date)        #  شروع می‌شود و خروجی‌اش  ضبط می‌شود "date" فرمان‎
  $ echo "$today"
  Mon Jul 26 13:16:02 MEST 2004

این مورد همچنین می‌تواند با فرمانهایی علاوه بر تخصیص‌ها، استفاده شود:

  $ echo "Today is $(date +%A), it's $(date +%H:%M)"
  Today is Monday, it's 13:21

این سطر فرمان، برنامه date را دو بار فراخوانی می‌کند، دفعه اول برای چاپ روز هفته، دفعه دوم برای زمان فعلی.

البته، این مورد می‌توانست در یک نوبت به این صورت انجام بشود:

  date "+Today is %A, it's %H:%M"

همچون در تمام جایگزینی‌ها، نتایج جایگزینی فرمان تحت تأثیر تفکیک کلمه قرار خواهد گرفت، مگر اینکه، کل آن در داخل نقل‌قول‌های دوگانه باشد.

جایگزینی‌های فرمان ممکن است به طور تو در تو، داخل یکدیگر باشند:

  IPs=($(awk /"$(</etc/myname)"/'{print $1}' /etc/hosts))

به طور درخور توجه، پوسته داخل یک جایگزینی فرمان، یک مضمون نقل‌قولی کاملاً جدید را شروع می‌کند. یعنی، نقل‌قولهای دوگانه داخل جایگزینی با نقل‌قولهای دوگانه در خارج از جایگزینی، یارگیری نمی‌شوند. بنابراین، چنین مواردی می‌تواند انجام بشود:

  echo "The IPs are $(awk /"$(</etc/myname)"/'{print $1}' /etc/hosts | tr '\n' ' ')"

خارجی‌ترین نقل‌قول‌ها یک شناسه منفرد را تعیین می‌کنند که به echo عبور داده خواهند شد. نقل‌قولهای دوگانه درونی از تفکیک کلمه یا بسط glob روی نتایج جایگزینی فرمان درونی ممانعت می‌کنند. دو گروه نقل‌قول دوگانه مستقل از یکدیگر هستند.

(جهت رویکرد مناسب‌تری برای مکشوف نمودن آدرس‌های IP محلی، IpAddress را ببینید.)

جایگزینی‌های فرمان، پوسته‌های فرعی را تولید می‌کنند، بنابراین همه تغییرات متغیرها، دایرکتوری کاری، و غیره در داخل جایگزینی فرمان، فقط بر نتیجه جایگزینی اثر می‌گذارد، و نه بر پوسته والد.

  $ var=$(cd ../../usr/bin; pwd)
  $ echo "$var"
  /usr/bin
  $ pwd
  /home/user

جایگزینی‌های فرمان تمام سطرهای جدید انتهایی خروجی فرمان درونشان را حذف می‌کنند. این مطلب انجام موارد رایجی از قبیل ‎foo=$(grep foo bar)‎ را برای مقداردهی متغیرها، بدون نیاز به یک مرحله دوم جهت حذف سطر جدید، میسر می‌سازد. گاهی اوقات، ممکن است سطر جدید را بخواهید -- برای مثال، موقعی که سعی می‌کنید یک فایل کامل را بدون از دست دادن داده‌ها(به استثنای بایت‌های NULL) داخل یک متغیر بخوانید:

  var=$(<file)   #  سطرجدیدِ انتهایی را حذف می‌کند‎

    # :راهکار عبور از آن‎
  var=$(cat file; printf x) var=${var%x}
مثالی از مترجم

قابلیت حمل

ترکیب ‎$(command)‎ توسط پوسته Korn، و BASH، و پوسته Posix پشتیبانی می‌شود. شل‌های قدیمی‌تر (به عنوان مثال پوسته Bourne) از ترکیبی به صورت: ‎`command`‎ استفاده می‌کنند. توجه کنید که کاراکترهای آپاستروف ‎'...'‎ نیستند، بلکه خطنشانه‌هایی هستند که از سمت چپ در بالا متمایل به سمت راست در پایین رسم می‌شوند: ‎`...`‎. این نشانه‌ها غالباً "backtick" یا نقل‌قول برعکس نامیده می‌شوند.

تو در تویی جایگزینی‌های فرمان با استفاده از ترکیب ‎`...`‎ بیشتر بغرنج است. باید از کاراکترهای \ استفاده شود:

  IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`
    
  # Very Bourne-ish: use the positional params as a pseudo array
  set -- `awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`

به طوری که می‌توان تصور کرد، پس از سطح تودرتویی بسیار سنگین و غیرقابل مهار می‌شود. پرسش و پاسخ شماره ۸۲ با تفصیل بیشتری تفاوتهای میان ‎$()‎ و ‎``‎ را مطرح می‌کند.

استفاده از ‎$(<file)‎ به جای ‎$(cat file)‎ یک Bashism(مترجم: ویژگی‌هایی که در posix وجود ندارد) است که به طور جزئی کارامدتر است (چون نیاز به انشعاب یک پردازش ‎cat(1)‎ ندارد)، اما به وضوح کمتر قابل حمل می‌باشد.


CategoryShell

  • جایگزینی فرمان (آخرین ویرایش ‎2011-06-03 13:03:11‎ توسط GreyCat)


    1. مترجم: برای وضوح مطلب ذکر مثالی از اجرای این دستورات با نمایش نتایج حاصله مفید خواهد بود.

        $ var=$(<test.txt)
        $ echo $var	# نقل‌قولی نشده
        line1 line2 line3 line6 line7 line8
        $ echo "$var"	# نقل‌قولی شده
        line1
        line2
        line3
        
        
        line6
        line7
        line8
        #	همان فایل با استفاده از راهکار ارائه شده
        $ var=$(cat $file; printf x) var=${var%x}
        $ echo $var	# نقل‌قولی نشده
        line1 line2 line3 line6 line7 line8
        $ echo "$var"	# نقل‌قولی شده
        line1
        line2
        line3
        
        
        line6
        line7
        line8
        		
        $    #    مطلب در مورد این سطر نهم در انتها است که در این حالت در متغیر‎
             #  حفظ گردیده است. در تدبیری که به کار رفته ابتدا در داخل جایگزینی‎
             #  یک کاراکتر به انتهای خروجی ضمیمه شده و سپس بیرون از جایگزینی آن‎
             #. کاراکتر حذف شده که در نتیجه سطر جدید در  جای خود باقی مانده است‎
      
      (بازگشت)