فصل هشتم - جانشینیها
در فصل قبل چگونگی دستیابی به یک متغیر با استفاده از کاراکتر $ شرح داده
شد. عملیات بازیابی مقدار یک کاراکتر عملیات جانشینی متغیر یا variable
substitution نامیده میشود. در این فصل چهار جانشینی زیر بررسی میشوند:
- جانشینی در نام فایلها(globbing)
- جانشینی پارامترها
- جانشینی دستورات
- جانشینی عملیات حسابی
محتویات[نهفتن] |
جانشینی در نام فایلها(globbing)
عمده ترین نوع جانشینی، جانشینی در نام فایلها است که globbing نامیده میشود.
در شل جانشینی نام فایلها، عملیاتی است که میتوان نام فایل را با استفاده از یک الگو گسترش داد.
جدول الگو که میتوان با استفاده از آنها از جانشینی نامفایل استفاده کرد به شرح زیر است:
* : وقوع صفر یا بیشتر از صفر کاراکتر از هر نوعی
? : وقوع یک کاراکتر از هر نوعی
[characters] : وقوع یک کاراکتر از لیست کاراکترهای مشخص شده در charachters
نکته: میتوان در هر دستوری که در آن از نام یک فایل استفاده میشود، از جانشینی نامفایل استفاده کرد.
استفاده از *
سادهترین راه برای جانشینی نامفایل استفاده از * به تنهایی است.
کاراکتر * به این معنی است که، شل میتواند صفر یا بیشتر از صفر تکرار از هر
کاراکتری را جایگزین کند. به عبارت دیگر فایل با هر نامی را جانشین * کند.
مثال:
$ls -a *
این دستور تمامی فایلها و محتوای تمام دایرکتوریها و زیر دایرکتوریها در مسیر جاری را نمایش میدهد.
در بسیار موارد استفاده از * به تنهایی میتواند مفید باشد، ولی قدرت
استفاده از آن در ترکیب با عبارات به صورت پیشوند، پسوند یا میانوند است که
هر کدام
در ادامه بررسی میشوند.
استفاده از * در پایان عبارات
شکل کلی استفاده از * در عبارات به صورت پسوندی به صورت زیر است:
command prefix*
که در آن command نام دستور و prefix عباراتی است که نامفایل با آن آغاز میشود.
مثال:
$ ls ch1*
این دستور نام تمام فایلها و دایرکتوریهایی که با عبارت ch1 آغاز میشوند را نشان میدهد که خروجی این دستور میتواند به شکل زیر باشد:
ch10-01 ch10-02 ch10-03 ch11-01 ch11-02 ch11-03
استفاده از * در آغاز عبارات
شکل کلی استفاده از * در عبارات به صورت پسوندی به صورت زیر است:
command *suffix
که در آن command نام دستور و suffix عباراتی است که نامفایل با آن پایان میابد.
مثال:
$ ls *doc
این دستور نام تمام فایلها و دایرکتوریهایی که با عبارت doc پایان میابد را نشان میدهد. که میتواند خروجی شبیه زیر تولید کند.
ch10-01.doc ch10-02.doc ch10-03.doc ch10-04.doc ch10-05.doc ch10-06.doc ch10-07.doc ch10-06.doc ch10-17.doc
استفاده از * در عبارات به صورت میانوند
شکل کلی استفاده از این دستور به صورت زیر است:
command prefix*suffix
که نشان دهندهی تمامی عباراتی است که با عبارت prefix شروع شده و با suffix اتمام مییابند.
مثال:
$ ls Backup*doc Backup of ch10-01.doc Backup of ch10-02.doc Backup of ch10-03.doc Backup of ch10-04.doc Backup of ch10-05.doc Backup of ch10-06.doc
همچنین امکان استفاده از چندین * در بین عبارات نیز وجود دارد.
مثال:
$ ls CGI*st*java CGIPost.java CGITester.java CGITest.java
استفاده از ?
استفاده از کاراکتر ? به این معنی است که، شل میتواند یک کاراکتر از هر نوعی را جایگزین کند.
کاراکتر ? نیز همانند کاراکتر * میتواند به صورت پیشوند، پسوند یا میانوندی مورد استفاده قرار بگیرد.
مثال:
$ ls ch0*.doc
که میتواند خروجی به شکل زیر داشته تولید کند:
ch01-1.doc ch01.doc ch05.doc ch06-2.doc ch01-2.doc ch02-1.doc ch050.doc ch06.doc ch01.doc ch02-2.doc ch06-1.doc ch060.doc ch02.doc ch03-2.doc ch04-1.doc ch040.doc ch020.doc ch03.doc ch04-2.doc ch05-1.doc ch03-1.doc ch030.doc ch4.doc ch5.doc
در این مثال فایل با نام ch0.doc، حتی اگر وجود داشته باشد هم نمایش داده نمیشود.
میتوان از چندین ? به صورت پشت سر هم یا جداگانه در عبارات استفاده کرد.
مثال:
$ ls ch??.doc ch01-1.doc ch010.doc ch05.doc ch06-2.doc ch01-2.doc ch02-1.doc ch050.doc ch06.doc ch01.doc ch02-2.doc ch06-1.doc ch060.doc ch02.doc ch03-2.doc ch04-1.doc ch040.doc ch020.doc ch03.doc ch04-2.doc ch05-1.doc ch03-1.doc ch030.doc
استفاده از الگو به شکل [characters]
دو مشکل عمدهی استفاده از کاراکترهای ؟ و * به شرح زیر است:
- جانشینی نام با هر نوع کاراکتری اعم از کاراکترهای ویژه مانند (-) .
- امکان استفاده از یک الگوی دقیقتر از حروف و اعداد در آن حالتها وجود ندارد.
برای حل مشکلات بالا میتوان از الگوی [characters] به صورت زیر استفاده کرد:
$command prefix[characters]suffix
که در این حالت characters ، کاراکترهایی است که شما برای جانشینی میتوانید استفاده کنید.
مثال:
$ ls ch0[0123456789].doc ch01.doc ch02.doc ch03.doc ch04.doc ch05.doc ch06.doc
که در آن نامفایل میتواند با یکی از اعداد ۰ تا ۹ جانشین شود.
نکته: به جای نوشتن کل کاراکترهای مورد نظر میتوان محدودهی آنها را با استفاده از (-) مشخص کرد.
مثال:دو عبارت زیر با هم برابرند:
$ ls ch0[0123456789].doc $ ls ch0[0-9].doc
همچنین ادغام چند محدوده یا ادغام این شکل از جانشینی با، با کاراکترهای * و ? امکان پذیر است.
مثالها:
$ ls [a-z]*
نمایش تمام فایلهایی که با یک حرف کوچک شروع میشوند
$ ls [A-Z]*
نمایش تمام فایلهایی که با یک حرف بزرگ شروع میشوند
$ ls [a-zA-Z]*
نمایش تمام فایلهایی که با یک حرف شروع میشوند
$ ls *[a-zA-Z0-9]
نمایش تمام فایلهایی که با یکی از اعداد یا حروف پایان مییابند
لغو جانشین شدن یک الگو با استفاده از !
برای جلوگیری در جانیشنی نامفایلها میتوان از کاراکتر ! به صورت زیر استفاده کرد:
command [!characters]
در این حالت کاراکترهایی که در داخل [] اعلان شدهاند جانشین نمیشوند.
مثال:
دو عبارت زیر با هم معادل هستند
$ ls [b-zA-Z0-9\-_\+\=\\\'\"\{\[\}\] $ ls [!a]*
این حالت زمانی مفید خواهد بود که شما بخواهید از جانشینی یک یا چند کاراکتر خاص جلوگیری کنید
نکته: جانشینی الگوها در نام فایلها، توسط خود شل انجام میشود، نه توسط دستور. به عنوان مثال، اگر در دایرکتوری جاری، فایلهایی که اسمشان با حرف a شروع میشود، سه فایل a1 و a2 و a3 باشند، در اینصورت دستور
$ ls a*
مثل دستور
$ ls a1 a2 a3
میماند، در واقع دستور ls متوجه نمیشود که شما از الگوی جانشینی بوسیلهٔ * استفاده کردهاید و فقط سه آرگومان دریافت میکند
نکته: اگر خود اسم/مسیر فایل شامل علامتهایی مثل * یا ? باشد، باید اسم فایل/مسیر فایل را داخل نقل یگانه یا دوگانه بگذارید (نقل یگانه مطمئنتر است). به این موضوع در فصل بعد پرداخته شده است.
جانشینی در پارامترها
استفاده از مقادیر پیشفرض
شکل کلی این حالت به صورت زیر است:
${parameter:-defaultValue} var=${parameter:-defaultValue}
اگر parameter مقدار دهی نشده باشد از defualtvalue استفاده میشود
مثال:
u=${1:-root}
در اینجا در صورتی که متغیر $1 مقدار دهی نشده باشد از متغیر root برای مقدار دهی u استفاده میشود
مثال:
اسکریپت زیر را در نظر بگیرید:
_jail_dir="${1:-/home/phpcgi}" echo "Setting php-cgi at ${_baroon_dir}..."
حالا این اسکریپت را به صورتهای زیر اجرا کنید و خروجی آن را بررسی کنید:
./script.sh /baroon ./script.sh /home/httpd/baroon ./script.sh
قرار دادن مقدار پیش فرض
شکل کلی این وضعیت به صورت زیر است:
${var:=value} var=${USER:=value}
در اینجا عمل انتصاب زمانی انجام میشود که متغیر USER دارای هیچ مقداری
نباشد. به عبارتی در صورتی که متغیر USER دارای مقدار باشد عمل انتصاب
انجام نمیشود.
مثال
اسکریپت زیر را در نظر بگیرید:
echo $USER echo ${USER:=foo} unset USER echo ${USER:=foo}
خروجی این اسکریپت به شکل زیر است:
baroon baroon foo
جانشینی در دستورات
در جانشینی دستورات شما قادر خواهید بود تا از خروجی یک دستور در یک دستور دیگر استفاده کنید.
شکل کلی استفاده از جانشینی در دستورات به صورت زیر است:
`command`
که در اینجا command میتواند هر کدام از دستورات شل باشد
توجه: مطمئن باشید که از کاراکتر `` استفاده میکنید. خطای رایج استفاده از ' (quote) به جای ` (back quote) است. برای تایپ این کاراکتر از دکمهای که بالای Tab قرار دارد استفاده کنید.
مثال:
DATE=`date`
خروجی دستور date در متغیر DATE ذخیره میشود
USERS=`who | wc -l `
تعداد کاربران در متغیر USERS ذخیره میشود
UP=`date ; uptime`
خروجی دو دستور date و uptime در متغیر UP ذخیره میشود
جانشینی در عبارات محاسباتی
در bash امکان استفاده از عبارات محاسباتی برای اعداد صحیح بدون استفاده از برنامههایی نظیر expr فراهم شده است.
شکل کلی استفاده از عبارات محاسباتی صحیح به صورت زیر است:
[expression]
و یا
((expression))
که در آن expression یک عبارت ریاضی مجاز به استفاده از عملگرهای / + - * و پرانتز () میباشد.
مثال:
foo=$[ ((5 + 3*2) - 4) / 2 ]
یا
foo=$(( ((5 + 3*2) - 4) / 2 ))
که در این مثال مقدار متغیر foo برابر ۳ میشود.
نکته: همانطور که اشاره شد از این جانشینی فقط برای اعداد صحیح میتوان استفاده کرد و حاصل همیشه باید یک عدد صحیح باشد، در نتیجه در مثال بالا متغیر foo به جای ۳.۵ ، مقدار ۳ را میپذیرد.
Eman ۱۵ فوریهٔ ۲۰۱۲، ساعت ۱۱:۵۱ (UTC)