یک wrapper، اسکریپت پوستهای است که یک فرمان سیستم یا برنامه سودمند را در خود جای میدهد تا یک مجموعه پارامتر را پذیرفته و به آن فرمان عبور بدهد. [1] Wrapping (بستهبندی) یک اسکریپت در اطراف یک فرمان پیچیده فراخوانی آن را آسانتر میکند. این کار مخصوصاً با sed و awk سودمند است.
یک اسکریپت sed یا awk به طور عادی به وسیله یک sed -e 'commands' یا awk 'commands' از خط فرمان فراخوانی میگردد. جای دادن چنین اسکریپتی در یک اسکریپت Bash فراخوانی آسانتر آن را میسر کرده، و آن را قابل استفاده مجدد میکند. این کار ترکیب کردن امکانات sed و awk، برای مثال لولهکشی خروجی مجموعهای از فرمانهای sed به awk، را نیز مقدور میسازد. سپس میتوانید مانند یک فایل ذخیره شده قابل اجرا، بدون دردسر تایپ مجدد در خط فرمان ، همان شکل اولیه یا ویرایش شده آن را، به طور مکرر فراخوانی کنید.
#!/bin/bash #این اسکریپت ساده سطرهای خالی را از یک فایل حذف میکند. #فاقد بازبینی وجود شناسه است. # #شاید مایل باشید انجام چنین کاری را به آن اضافه کنید: # # # # # # # sed -e /^$/d "$1" #مشابه با sed -e '/^$/d' filename فراخوانی شده از خط فرمان. #-e یعنی یک فرمان «editing» در ادامه میآید (اینجا اختیاری است). #^ بیانگر ابتدای سطر، و $ نشان دهنده انتهای سطر است. #این الگو با سطرهایی منطبق است که بین ابتدا و انتهای آنها چیزی #+وجود ندارد، یعنی سطرهای خالی. #d فرمان delete است. #نقلقول کردن شناسه خط فرمان، وجود فضای سفید و کاراکترهای خاص در #+نام فایل را امکانپذیر میکند. #توجه نمایید که این اسکریپت واقعاً فایل مقصد را تغییر نمیدهد. #اگر نیاز به انجام این کار دارید، خروجی آن را تغییر مسیر بدهید. exit
مثال 36-2. یک wrapper پوسته اندکی پیچیدهتر
#!/bin/bash #اسکریپتی که الگویی را جایگزین الگوی دیگری در #+یک فایل میکند، یعنی «sh subst.sh Smith Jones letter.txt» #در فایل letter.txt کلمه Jones را با Smith تعویض میکند. ARGS=3 #اسکریپت سه شناسه لازم دارد. E_BADARGS=85 #تعداد شناسهها اشتباه است. if [ $# -ne "$ARGS" ] then echo "Usage: `basename $0` old-pattern new-pattern filename" exit $E_BADARGS fi old_pattern=$1 new_pattern=$2 if [ -f "$3" ] then file_name=$3 else echo "File \"$3\" does not exist." exit $E_BADARGS fi # #اینجا جایی است که بخش عمده کار انجام میشود. sed -e "s/$old_pattern/$new_pattern/g" $file_name # #البته s در sed فرمان جایگزینی است، و #+/pattern/ آدرس انطباق را نشان میدهد. #g یا نشانوند سراسری باعث جایگزینی هر مورد انطباق #+$old_pattern در هر سطر، نه فقط در سطر اول میگردد. #برای توضیح دقیق و عمیق، مستندات sed را بخوانید. exit $? #برای نوشتن در یک فایل، خروجی این اسکریپت را تغییر مسیر بدهید.
مثال 36-3. یک wrapper پوسته عمومی که در یک فایل log مینویسد
#!/bin/bash # #wrapper پوسته عمومی که عملیاتی را انجام میدهد و #+آن را در فایل ثبت رخداد مینویسد. DEFAULT_LOGFILE=logfile.txt #دو متغیر زیر را تنظیم کنید. OPERATION= #میتواند زنجیر پیچیدهای از فرمانها باشد، #+برای مثال یک اسکریپت awk یا یک لوله . . . LOGFILE= if [ -z "$LOGFILE" ] then #اگر تنظیم نیست، پیشفرض شود به ... LOGFILE="$DEFAULT_LOGFILE" fi #شناسه های خط فرمان برای عملیات، در صورت حضور. OPTIONS="$@" #واقعهنگاری آن. echo "`date` + `whoami` + $OPERATION "$@"" >> $LOGFILE #اکنون، انجام عملیات. exec $OPERATION "$@" #انجام واقعهنگاری قبل از عملیات ضروری است. چرا؟
مثال 36-4. یک wrapper پوسته پیرامون یک اسکریپت awk
#!/bin/bash #جدولی از کاراکترهای اسکی چاپ میکند. START=33 #محدوده کاراکترهای اسکی قابل چاپ (دسیمال). END=127 #برای کاراکترهای غیرقابل چاپ (> 127) کار نمیکند. echo " Decimal Hex Character" #سرآیند. echo " ------- --- ---------" for ((i=START; i<=END; i++)) do echo $i | awk '{printf(" %3d %2x %c\n", $1, $1, $1)}' #فرمان داخلی printf خود Bash در این مضمون کار نخواهد کرد: # done exit 0 #خروجی این اسکریپت را به یک فایل تغییر مسیر بدهید #+یا به صورت sh pr-asc.sh | more لولهکشی کنید
مثال 36-5. یک wrapper پوسته پیرامون یک اسکریپت awk دیگر
#!/bin/bash #یک ستون مشخص شده (از اعداد) در یک فایل هدف را جمع میزند. #اعداد اعشاری (دسیمال) نیز قبول است، زیرا awk میتواند با آنها کار کند. ARGS=2 E_WRONGARGS=85 if [ $# -ne "$ARGS" ] #بازبینی برای صحیح بودن تعداد شناسههای خط فرمان. then echo "Usage: `basename $0` filename column-number" exit $E_WRONGARGS fi filename=$1 column_number=$2 #عبور دادن متغیرهای پوسته به بخش awk اسکریپت یک مقدار ماهرانه است. #یک روش، نقلقولِ پر قدرتِ متغیرِ اسکریپت Bash در داخل اسکریپت awk است. # # #این کار در اسکریپت awk جاسازی شده زیر انجام میشود. #برای جزییات بیشتر، مستندات awk را ببینید. #در اینجا اسکریپت چند سطری awk چنین فراخوانی میشود # # # # # #شروع اسکریپت awk # awk ' { total += $'"${column_number}"' } END { print total } ' "$filename" # #پایان اسکریپت awk #ممکن است عبور دادن متغیرهای پوسته به یک اسکریپت تعبیه شده awk بیخطر #+نباشد، بنابراین Stephane Chazelas جایگزین پایین را پیشنهاد میکند: # # # # # # # # exit 0
برای اسکریپتهایی که نیازمند یک ابزار منفرد همه کاره، یک چاقوی نظامی سوییسی هستند، Perl وجود دارد. Perl تواناییهای
مثال 36-6. پرل تعبیه شده در یک اسکریپت Bash
#!/bin/bash #فرمانهای پوسته میتوانند مقدم بر اسکریپت پرل باشند. echo "This precedes the embedded Perl script within \"$0\"." echo "===============================================================" perl -e 'print "This line prints from an embedded Perl script.\n";' #مانند sed، پرل نیز از گزینه -e استفاده میکند. echo "===============================================================" echo "However, the script may also contain shell and system commands." exit 0
حتی ترکیب کردن یک اسکریپت Bash و اسکریپت Perl در داخل یک فایل نیز امکانپذیر است. نسبت به اینکه اسکریپت چگونه فراخوانی بشود، یا بخش Bash یا بخش Perl اجرا خواهد گردید.
مثال 36-7. اسکریپهای ترکیب شده Bash و Perl
#!/bin/bash # echo "Greetings from the Bash part of the script, $0." #اینجا فرمانهای Bash بیشتری میتواند ادامه یابد. exit #پایان بخش Bash اسکریپت. #=============================================== #!/usr/bin/perl #این بخش اسکریپت باید به این طریق فراخوانی گردد: # print "Greetings from the Perl part of the script, $0.\n"; #به نظر نمیرسد پرل به echo تمایل داشته باشد ... #اینجا فرمانهای Perl بیشتری میتواند ادامه یابد. #پایان بخش Perl اسکریپت.
bash$ bash bashandperl.sh Greetings from the Bash part of the script. bash$ perl -x bashandperl.sh Greetings from the Perl part of the script.
البته، حتی جای دادن زبانهای اسکریپتنویسی خارجی دیگر نیز در درون wrapperهای پوسته امکانپذیر است. برای مثال Python ...
مثال 36-8. پایتون جاسازی شده در یک اسکریپت Bash
#!/bin/bash # #فرمانهای پوسته میتوانند جلوتر از اسکریپت پایتون قرار داشته باشند. echo "This precedes the embedded Python script within \"$0.\"" echo "===============================================================" python -c 'print "This line prints from an embedded Python script.\n";' #بر خلاف sed و perl، پایتون گزینه -c را به کار میبرد. python -c 'k = raw_input( "Hit a key to exit to outer script. " )' echo "===============================================================" echo "However, the script may also contain shell and system commands." exit 0
با بستهبندی یک اسکریپت اطراف mplayer و سرویسدهنده ترجمه گوگل، میتوانید چیزی تولید کنید که به شما جواب بدهد.
مثال 36-9. اسکریپتی که صحبت میکند
#!/bin/bash #با احترام برگرفته از: # #برای اینکه اسکریپت کار کند، شما باید آنلاین باشید، طوری #+که بتوانید سرویسدهنده ترجمه گوگل را دستیابی کنید. #البته، mplayer نیز باید روی کامپیوتر شما موجود باشد. speak() { local IFS=+ #فراخوانی mplayer، سپس متصل شدن به سرور ترجمه گوگل. /usr/bin/mplayer -ao alsa -really-quiet -noconsolecontrols \ "http://translate.google.com/translate_tts?tl=en&q=$*" #گوگل ترجمه میکند، اما صحبت هم میتواند بکند. } LINES=4 spk=$(tail -$LINES $0) #دنباله پایانی همین اسکریپت! speak "$spk" exit #
مثال جالبی از یک wrapper پوسته پیچیده، اسکریپت undvd نوشته Martin Matusiak است، که یک واسط خط فرمان با استفاده آسان برای برنامه سودمند پیچیده mencoder فراهم میکند. یک نمونه دیگر Ext3Undel، نوشته Itzchak Rehberg میباشد، که یک مجموعه اسکریپت برای بازیابی فایلهای حذف شده در یک ساختار فایل ext3 است.
[1] | در واقع، تعدادی از برنامههای مفید لینوکس، wrapperهای پوسته هستند. برخی نمونهها عبارتند از، /usr/bin/pdf2ps، /usr/bin/batch، و /usr/bin/xmkmf. |