هر گاه شما یک سطرِ فرمان تایپ میکنید و کلید اینتر را فشار میدهید، bash قبل از انجام دادن فرمان شما چند پردازش روی آن اجرا میکند. ما در چند موقعیت دیدهایم که چگونه یک رشته کاراکتر ساده، به عنوان مثال «
[me@linuxbox me]$ echo this is a test
this is a test
تا حدی سر راست است. هر شناسه عبور داده شده به echo نمایش داده میشود. بیایید مثال دیگری را امتحان کنیم:
[me@linuxbox me]$ echo *
Desktop Documents ls-output.txt Music Pictures Public Templates
Videos
پس دقیقاً چه اتفاقی رخ میدهد؟ چرا echo این «*» را چاپ نمیکند؟ به طوری که از کارمان با کاراکترهای عام به یاد دارید، کاراکتر «
ساز و کاری که کاراکترهای عام توسط آن عمل میکنند
[me@linuxbox me]$ ls
Desktop ls-output.txt Documents Music Pictures Public Templates Videos
میتوانستیم بسطهای زیر را اجرا کنیم:
[me@linuxbox me]$ echo D*
Desktop Documents
و:
[me@linuxbox me]$ echo *s
Documents Pictures Templates Videos
یا حتی:
[me@linuxbox me]$ echo [[:upper:]]*
Desktop Documents Music Pictures Public Templates Videos
و نگریستن به ماورای دایرکتوری خانگیمان:
[me@linuxbox me]$ echo /usr/*/share
/usr/kerberos/share /usr/local/share
به طوری که ممکن است شما از معرفی فرمان cd به خاطر بیاورید، کاراکتر مد («
[me@linuxbox me]$ echo ~
/home/me
اگر کاربر
[me@linuxbox me]$ echo ~foo
/home/foo
پوسته اجازه میدهد به وسیله بسط، محاسبه انجام بشود. این مورد به ما امکان میدهد اعلان پوسته را به عنوان یک ماشین حساب به کار ببریم:
[me@linuxbox me]$ echo $((2 + 2))
4
بسط حسابی این قالب را استفاده میکند:
$((expression))
که در آن «expression» یک عبارت حسابی متشکل از متغیرها و عملگرهای محاسباتی است.
بسط حسابی فقط اعداد صحیح (اعداد کامل، نه اعشاری) را پشتیبانی میکند، اما کاملاً میتواند عملیات متعدد مختلفی را انجام بدهد.
در بسط حسابی فاصلهها با اهمیت نیستند و عبارت میتواند تو در تو باشد. به عنوان مثال، برای پنج به توان دو ضربدر سه:
[me@linuxbox me]$ echo $(($((5**2)) * 3))
75
پرانتزهای منفرد میتوانند برای گروهبندی عبارتهای فرعی به کار بروند. با این روش، ما میتوانیم مثال فوق را بازنویسی کنیم و همان نتیجه را به جای دو بسط با کاربرد یک بسط به دست بیاوریم:
[me@linuxbox me]$ echo $(((5**2) * 3))
75
این هم یک مثال با استفاده از عملگرهای تقسیم و باقیمانده. به اثر تقسیم صحیح توجه کنید:
[me@linuxbox me]$ echo Five divided by two equals $((5/2))
Five divided by two equals 2
[me@linuxbox me]$ echo with $((5%2)) left over.
with 1 left over.
گویا عجیبترین بسط،
[me@linuxbox me]$ echo Front-{A,B,C}-Back
Front-A-Back Front-B-Back Front-C-Back
الگوهایی که بسط ابرو داده میشوند ممکن است شامل یک بخش پیشتاز به نام
[me@linuxbox me]$ echo Number_{1..5}
Number_1 Number_2 Number_3 Number_4 Number_5
یک محدوده از حروف با ترتیب وارونه:
[me@linuxbox me]$ echo {Z..A}
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
بسط ابرو میتواند تو در تو باشد:
[me@linuxbox me]$ echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b
برای چه کاری مناسب است؟ رایجترین کاربرد آن برای ساختن فهرستهایی از فایلها یا دایرکتوریهایی است که باید ایجاد گردند. برای مثال، اگر شما یک عکاس بودید و مجموعه بزرگی از تصاویر داشتید که میخواستید آنها را نسبت به سال و ماه مرتب کنید، اولین کاری که شاید شما انجام بدهید ایجاد یک گروه دایرکتوریهای نامگذاری شده در قالب «سال-ماه» است. در این روش، نام دایرکتوریها به ترتیب تاریخی رخداد مرتب خواهند شد. شما میتوانستید لیست کامل دایرکتوریها را به تفصیل تایپ کنید، اما این کارِ خیلی زیادی است و متمایل به خطا نیز هست. به جای آن، شما میتوانستید این مورد را انجام بدهید:
[me@linuxbox me]$ mkdir Photos
[me@linuxbox me]$ cd Photos
[me@linuxbox Photos]$ mkdir {2007..2009}-0{1..9} {2007..2009}-{10..12}
[me@linuxbox Photos]$ ls
2007-01 2007-07 2008-01 2008-07 2009-01 2009-07 2007-02 2007-08 2008-02 2008-08 2009-02 2009-08 2007-03 2007-09 2008-03 2008-09 2009-03 2009-09 2007-04 2007-10 2008-04 2008-10 2009-04 2009-10 2007-05 2007-11 2008-05 2008-11 2009-05 2009-11 2007-06 2007-12 2008-06 2008-12 2009-06 2009-12
نسبتاً ماهرانه!
ما در این درس فقط میخواهیم به طور خلاصه
[me@linuxbox me]$ echo $USER
me
برای دیدن فهرستی از متغیرهای در دسترس، این را امتحان کنید:
[me@linuxbox me]$ printenv | less
ممکن است شما متوجه شدهاید که با انواع دیگر بسط، اگر یک الگو را اشتباه تایپ کنید، بسط صورت نخواهد گرفت و فرمان echo به سادگی الگوی تایپ شدهِ اشتباه را نمایش خواهد داد. با بسط پارامتر، در صورتیکه شما املای نام متغیر را اشتباه کنید، باز هم بسط انجام خواهد شد، اما به یک رشته تهی:
[me@linuxbox me]$ echo $SUER
[me@linuxbox ~]$
[me@linuxbox me]$ echo $(ls)
Desktop Documents ls-output.txt Music Pictures Public Templates
Videos
یکی از موارد مورد پسند من چیزی مانند این است:
[me@linuxbox me]$ ls -l $(which cp)
-rwxr-xr-x 1 root root 71516 2007-12-05 08:58 /bin/cp
در اینجا ما نتایج which cp را به عنوان یک شناسه به فرمان ls عبور دادهایم، به موجب آن، فهرستی از برنامه cp را بدون دانستن نام مسیر کامل آن به دست میآوریم. ما فقط به فرمانهای ساده محدود نیستیم. خط لولههای کامل هم میتوانند استفاده شوند (تنها بخشی از خروجی نشان داده شده):
[me@linuxbox me]$ file $(ls /usr/bin/* | grep bin/zip)
/usr/bin/bunzip2: /usr/bin/zip: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped /usr/bin/zipcloak: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped /usr/bin/zipgrep: POSIX shell script text executable /usr/bin/zipinfo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped /usr/bin/zipnote: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped /usr/bin/zipsplit: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
در این مثال، نتایج خط لوله لیست شناسههای فرمان file شدهاند. یک ترکیب دستوری پیشنهادی در برنامههای پوسته قدیمیتر برای جایگزینی فرمان هست که در bash نیز پشتیبانی شده است. آن ترکیب به جای علامت دلار و پرانتزها از نقلقولهای وارونه استفاده میکند:
[me@linuxbox me]$ ls -l `which cp`
-rwxr-xr-x 1 root root 71516 2007-12-05 08:58 /bin/cp
اکنون که دیدهایم پوسته به روشهای بسیاری میتواند بسطها را انجام بدهد، وقت آن است که یاد بگیریم، ما چطور میتوانیم آن را کنترل نماییم. این مثال را در نظر بگیرید:
[me@linuxbox me]$ echo this is a test
this is a test
یا:
[me@linuxbox me]$ [me@linuxbox ~]$ echo The total is $100.00
The total is 00.00
در مثال نخست، تفکیک کلمه توسط پوسته فضاهای سفید اضافی در فهرست شناسههای فرمان echo را پاک کرده است. در مثال دوم، بسط پارامتر یک رشته تهی برای مقدار
اولین نوع نقلقولی که به آن خواهیم پرداخت نقلقول دوگانه است، تمام کاراکترهای خاص مورد استفاده پوسته داخل نقلقول دوگانه معنای ویژه خود را از دست میدهند و به عنوان کاراکترهای معمولی با آنها رفتار میگردد. موارد استثنا عبارتند از
[me@linuxbox me]$ ls -l two words.txt
ls: cannot access two: No such file or directory ls: cannot access words.txt: No such file or directory
با کاربرد نقلقولهای دوگانه، شما میتوانید تفکیک کلمه را متوقف کنید و نتیجه دلخواه را به دست آورید، بعلاوه شما حتی میتوانید عیب را برطرف نمایید:
[me@linuxbox me]$ ls -l "two words.txt"
-rw-rw-r-- 1 me me 18 2008-02-20 13:03 two words.txt
[me@linuxbox me]$ mv "two words.txt" two_words.txt
در اینجا، اکنون ما نباید به تایپ کردن آن نقلقولهای ناخوشایند ادامه بدهیم. به خاطر داشته باشید داخل نقلقولهای دوگانه، بسط پارامتر، بسط حسابی، و جایگزینی فرمان بازهم رخ میدهند:
[me@linuxbox me]$ echo "$USER $((2+2)) $(cal)"
me 4 February 2008 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
ما باید زمان کوتاهی را به تاثیر نقلقولهای دوگانه بر جایگزینی فرمان بپردازیم. ابتدا بیایید کمی عمیقتر نگاه کنیم که تفکیک کلمه چگونه کار میکند. در مثال قدیمیتر، ما دیدیم در زدودن فاصلههای اضافه از متن، تفکیک کلمه چگونه ظاهر میشود:
[me@linuxbox me]$ echo this is a test
this is a test
به طور پیشفرض، تفکیک کلمه حضور فاصلهها، tabها، و سطرهای جدید (کاراکترهای تعویض سطر) را جستجو میکند و با آنها به عنوان جداکنندههای میان کلمات رفتار مینماید. این به معنای آن است که فاصلهها، tabها، و سطرهای جدیدِ نقلقولی نشده به عنوان بخشی از متن به حساب نمیآیند. آنها فقط به عنوان جداکنندهها خدمت میکنند. چون آنها کلمات را به شناسههای متمایز جدا میکنند، سطر فرمان مثال ما شامل یک فرمانِ دنبال شده با چهار شناسهِ قابل تشخیص است. در صورتیکه ما نقلقولهای دوگانه را اضافه کنیم:
[me@linuxbox me]$ echo "this is a test"
this is a test
تفکیک کلمه منکوب میگردد و فاصلههای گنجانده شده به عنوان جدا کنندهها به حساب نمیآیند، بلکه آنها بخشی از شناسه میشوند. وقتی نقلقولهای دوگانه افزوده میشوند، سطر فرمان ما شامل یک فرمانِ دنبال شده با یک شناسه منفرد است. اینکه سطرهای جدید توسط ساز و کار تفکیک کلمه به عنوان جداکننده به شمار میروند باعث یک تاثیر جالب توجه، اگرچه فریبنده، بر جایگزینی فرمان میگردد. مورد زیر را ملاحظه کنید:
[me@linuxbox me]$ echo $(cal)
February 2008 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
[me@linuxbox me]$ echo "$(cal)"
February 2008 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
در نمونه نخست، جایگزینی فرمان نقلقولی نشده به یک سطر فرمانِ سی و هشت شناسهای منجر میشود. در دومی، یک سطر فرمان با یک شناسه که شامل فاصلهها و سطرهای جدید جاسازی شده است.
اگر شما احتیاج داشته باشید تمام بسطها را خاموش کنید، نقلقولهای منفرد را استفاده میکنید. این هم مقایسهای بین نقلقول نشده، نقلقولهای دوگانه، و نقلقولهای منفرد:
[me@linuxbox me]$ echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
text /home/me/ls-output.txt a b foo 4 me
[me@linuxbox me]$ echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
text ~/*.txt {a,b} foo 4 me
[me@linuxbox me]$ echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
به طوریکه میتوانید مشاهده کنید، با هر مرحله بعدیِ نقلقول کردن، بسطهای بیشتر و بیشتری خاموش میگردند.
گاهی اوقات شما میخواهید تنها یک کاراکتر منفرد را نقلقول کنید. برای انجام این کار، میتوانید یک
[me@linuxbox me]$ echo "The balance for user $USER is: \$5.00"
The balance for user me is: $5.00
استفاده از معاف کردن برای زدودن معنای ویژه یک کاراکتر در نام یک فایل نیز متداول است. برای مثال، استفاده از کاراکترهایی در نام فایل که به طور معمول برای پوسته دارای معنای خاص هستند، امکانپذیر است. اینها میتوانند شامل
[me@linuxbox me]$ mv bad\&filename good_filename
برای اجازه دادن به حضور یک کاراکتر
اگر به صفحههای man برای هر برنامه نوشته شده توسط پروژه گنو نگاه کنید، متوجه خواهید گردید که علاوه بر گزینههای خط فرمانِ شاملِ یک خط تیره و یک کاراکتر، نامهای گزینه بلند نیز وجود دارند که با دو خط تیره شروع میشوند. برای مثال،موارد زیر مترادف هستند:
ls -r ls --reverse
چرا آنها هر دو پشتیبانی میشوند؟ شکل کوتاه برای تایپ کنندههای کُند در خط فرمان است و شکل بلند بیشتر برای اسکریپتها، اگر چه برخی گزینهها ممکن است فقط به شکل بلند باشند. من گاهی اوقات گزینههای مبهم به کار میبرم، و در صورتیکه باید بعد از ماهها اسکریپتی را که نوشتهام بازبینی کنم شکل بلند را مفید مییابم. دیدن گزینه بلند کمک میکند ملتفت شوم گزینه چه کار میکند، رهایی بخشیدن من از یک مراجعه به صفحه man. اندکی تایپ بیشتر در حال، مقدار زیادی کار کمتر در آینده. تنبلی پشتیبانی میشود.
همچنانکه شاید شما حدس بزنید، استفاده از شکل بلند گزینهها میتواند یک سطر فرمان منفرد را خیلی طولانی کند. برای مبارزه با این مشکل، میتوانید از یک
ls -l \ --reverse \ --human-readable \ --full-time
کاربرد backslash به این روش به ما امکان میدهد سطرهای جدید را در فرمان خود درج کنیم. توجه نمایید که برای آنکه این ترفند کار کند، سطرجدید باید به طور بدون فاصله پس از backslash تایپ شود. اگر شما یک فاصله پس از backslash قرار بدهید، کاراکتر فاصله صرفنظر خواهد شد، نه سطرجدید. Backslashها برای درج کاراکترهای خاص داخل متن ما نیز به کار میروند. اینها
کاراکتر گریز |
نام |
استفادههای امکانپذیر |
\n |
سطرجدید |
افزودن سطرهای خالی به متن |
\t |
tab |
درج tabهای افقی به متن |
\a |
هشدار |
ایجاد صدای بوق کوتاه ترمینال |
\\ |
backslash |
یک |
\f |
تغذیه کاغذ |
فرستادن این کاراکتر به چاپگرِ شما صفحه رابیرون میدهد |
استفاده از این کاراکترهای گریزِ backslash بسیار رایج است. این اندیشه ابتدا در زبان برنامهنویسی C ظاهر گردید. امروزه، شل، C++، پرل، پایتون، awk، tcl، و دیگر زبانهای برنامهنویسی این تدبیر را به کار میبرند. کاربرد فرمان echo با گزینه
[me@linuxbox me]$ echo -e "Inserting several blank
lines\n\n\n"
Inserting several blank lines
[me@linuxbox me]$ echo -e
"Words\tseparated\tby\thorizontal\ttabs."
Words separated by horizontal tabs[me@linuxbox me]$ echo -e "\aMy computer went \"beep\"."