فرمانهای مؤثر بر متن و فایلهای متنی
برنامه سودمند مرتبسازی فایل، بیشتر اوقات به عنوان فیلتر در یک لوله به کار میرود. این فرمان یک جریان متن یا فایل را به طرف جلو یا عقب یا براساس کلیدهای مختلف یا وضعیت کاراکترها مرتب میکند. با استفاده از گزینه -m فایلهای از قبل مرتب شده را با هم ادغام میکند. صفحه info گزینهها و امکانات بسیار آن را فهرست میکند. مثال 11-10، مثال 11-11، و مثال A-8 را ببینید.
مرتبسازی Topological، خواندن جفت رشتههای جداشده با فضای سفید و مرتب کردن آنها مطابق با الگوهای ورودی. هدف اولیه tsort فراهم نمودن لیستی از وابستگیها برای یک نگارش منسوخ از پیونددهنده ld در یک نگارش «قدیمی» یونیکس بود.
نتایج حاصل از tsort معمولاً با نتایج حاصل از دستور استاندارد sort فوق، تفاوت محسوسی دارند.
این فیلتر سطرهای تکراری را از یک فایل مرتبشده حذف میکند. بیشتر اوقات به صورت جفت شده با sort در یک لوله دیده میشود.
cat list-1 list-2 list-3 | sort | uniq > final.list #فایلهای list را بهم متصل میکند، #آنها را مرتب میسازد، #سطرهای تکراری را حذف میکند، #و سرانجام نتیجه را در یک فایل خروجی مینویسد.
گزینه مفید -c تعداد تکرار هر سطر فایل ورودی را به آن پیشوند میکند.
bash$ cat testfile This line occurs only once. This line occurs twice. This line occurs twice. This line occurs three times. This line occurs three times. This line occurs three times. bash$ uniq -c testfile 1 This line occurs only once. 2 This line occurs twice. 3 This line occurs three times. bash$ sort testfile | uniq -c | sort -nr 3 This line occurs three times. 2 This line occurs twice. 1 This line occurs only once.
رشته فرمان sort INPUTFILE | uniq -c | sort -nr فهرستی از فراوانی تکرارها در فایل INPUTFILE فراهم میکند (گزینه -nr برای sort باعث ترتیب عددی برعکس میشود). این الگو در تجزیه و تحلیل فایلهای ثبت رخداد و فهرست واژهنامهها، و هرجایی که لازم باشد ساختار کلمهای یک سند وارسی بشود، مورد استفاده مییابد.
مثال 16-12. تجزیه و تحلیل فراوانی کلمه
#!/bin/bash # #این یک نسخه کارآمدتر از اسکریپت wf2.sh است. # ARGS=1 E_BADARGS=85 E_NOFILE=86 if [ $# -ne "$ARGS" ] # then echo "Usage: `basename $0` filename" exit $E_BADARGS fi if [ ! -f "$1" ] # then echo "File \"$1\" does not exist." exit $E_NOFILE fi # # sed -e 's/\.//g' -e 's/\,//g' -e 's/ /\ /g' "$1" | tr 'A-Z' 'a-z' | sort | uniq -c | sort -nr # # # #+ #+ #Arun Giridhar اصلاح کد فوق به این صورت را پیشنهاد میکند: # # #+ # #«این یک مرتبسازی مبنایی کارآمد است، اول روی ستون دارای حداقل اهمیت (کلمه #+یا رشته، به طور دلخواه حساس به حالت حروف) و بعد روی ستون دارای بیشترین #+اهمیت (تعداد تکرارها).» # #همچنانکه Frank Wang توضیح میدهد، کد فوق معادل است با: #+ #+و کد پایین هم کار میکند: #+ # exit 0 # # #(1 فرمانهای sed برای فیلتر کردن سایر کاراکترهای نشانهگذاری، #+از قبیل سمیکالن را اضافه کنید. #(2 اسکریپت را برای فیلتر کردن فاصلههای چندتایی و سایر فضای #+سفیدها نیز ویرایش کنید.
bash$ cat testfile This line occurs only once. This line occurs twice. This line occurs twice. This line occurs three times. This line occurs three times. This line occurs three times. bash$ ./wf.sh testfile 6 this 6 occurs 6 line 3 times 3 three 2 twice 1 only 1 once
فیلتر expand کاراکترهای tab را به فاصله تبدیل میکند. بیشتر اوقات در یک pipe استفاده میشود.
فیلتر unexpand فاصلهها را به tab تبدیل میکند. این فیلتر اثر expand را وارونه میکند.
ابزاری برای استخراح فیلدهای فایلها. مشابه فرمان print $N در awk، اما محدودتر است. ممکن است در اسکریپت، استفاده از cut آسانتر از awk باشد. گزینههای بویژه با اهمیت این فرمان، -d (جداکننده) و -f (مشخصکننده فیلد) هستند.
کاربرد cut برای به دست آوردن فهرستی از سیستمفایلهای متصلشده:
cut -d ' ' -f1,2 /etc/mtab
کاربرد cut برای لیست کردن نگارش کرنل و سیستمعامل:
uname -a | cut -d" " -f1,3,11,12
کاربرد cut برای استخراج سرآیند پیغامها از یک پوشه e-mail:
bash$ grep '^Subject:' read-messages | cut -c10-80 Re: Linux suitable for mission-critical apps? MAKE MILLIONS WORKING AT HOME!!! Spam complaint Re: Spam complaint
کاربرد cut برای تجزیه یک فایل:
#فهرست تمام کاربران در فایل /etc/passwd. FILENAME=/etc/passwd for user in $(cut -d: -f1 $FILENAME) do echo $user done #با تشکر از Oleg Philon برای این پیشنهاد.
cut -d ' ' -f2,3 filename معادل با awk -F'[ ]' '{ print $2, $3 }' filename است.
حتی تعیین نمودن یک کاراکتر تعویض سطر به عنوان جداکننده، امکانپذیر است. در واقع ترفند آن، جاسازی تعویض سطر (RETURN) در رشته فرمان است.
bash$ cut -d' ' -f3,7,19 testfile This is line 3 of testfile. This is line 7 of testfile. This is line 19 of testfile. Jaka Kranjc برای توضیح این مورد متشکرم. |
همچنین مثال 16-48 را مشاهده نمایید.
ابزاری برای ادغام فایلهای مختلف با یکدیگر در یک فایل واحدِ چند ستونی. در ترکیب با cut، برای ایجاد فایلهای ثبت رخداد سیستم مفید است.
bash$ cat items alphabet blocks building blocks cables bash$ cat prices $1.00/dozen $2.50 ea. $3.75 bash$ paste items prices alphabet blocks $1.00/dozen building blocks $2.50 ea. cables $3.75
این فرمان را به عنوان یک عموزاده تک منظوره paste در نظر بگیرید. این برنامه قدرتمند، ادغام دو فایل به یک سبک معنادار را میسر میکند که این در اصل نگارش سادهای از یک بانک اطلاعات رابطهای تولید میکند.
فرمان join دقیقاً روی دو فایل عمل میکند، اما فقط سطرهای دارای یک فیلد مشترک برچسب (معمولاً برچسب عددی) را به یکدیگر وصل میکند، و نتیجه را در stdout مینویسد. فایلهایی که قرار است متصل شوند باید بر اساس فیلد برچسب مرتب شده باشند تا یارگیریها به طور صحیح انجام گردد.
File: 1.data 100 Shoes 200 Laces 300 Socks
File: 2.data 100 $40.00 200 $1.00 300 $2.00
bash$ join 1.data 2.data File: 1.data 2.data 100 Shoes $40.00 200 Laces $1.00 300 Socks $2.00
فیلد برچسب فقط یکبار در خروجی ظاهر میشود. |
سطرهای ابتدای یک فایل را در stdout لیست میکند. پیشفرض آن 10 سطر است، اما یک عدد متفاوت نیز میتواند تعیین بشود. فرمان دارای تعدادی گزینه جالب توجه است.
مثال 16-13. کدام فایلها اسکریپت هستند؟
#!/bin/bash # TESTCHARS=2 # SHABANG='#!' #اسکریپتها با یک«sha-bang» شروع میشوند. for file in * # do if [[ `head -c$TESTCHARS "$file"` = "$SHABANG" ]] # #گزینه -c با head به جای سطرها(پیشفرض) تعداد کاراکتر #+معین شده را بیرون میدهد. then echo "File \"$file\" is a script." else echo "File \"$file\" is *not* a script." fi done exit 0 # # #(1 این اسکریپت را برای دریافت یک دایرکتوری به عنوان #+ #+ # #(2 به طوری که مشخص است، این اسکریپت پاسخ «مثبت کاذب» جهت #+اسکریپتهای Perl، awk، و سایر زبانهای اسکریپتنویسی را #نیز ارایه میدهد. این مورد را اصلاح کنید.
مثال 16-14. تولید اعداد تصادفی ده رقمی
#!/bin/bash # #اسکریپت توسط Stephane Chazelas نوشته شده. head -c4 /dev/urandom | od -N4 -tu4 | sed -ne '1s/.* //p' # # # #head: #گزینه -c4 چهار بایت نخست را میگیرد. #od: #گزینه -N4 خروجی را به چهار بایت محدود میسازد. #گزینه -tu4 قالب دسیمال بدون علامت برای خروجی انتخاب میکند. #sed: #گزینه -n در ترکیب با نشانه p برای فرمان s فقط سطرهای منطبق #شده را بیرون میدهد. #مؤلف این اسکریپت عمل sed را به صورت زیر شرح میدهد. # # #فرض کنید خروجی تا رسیدن به sed # #sed شروع به خواندن کاراکترها میکند: 0000000 1198195154\n # #+پردازش سطر نخست (0000000 1198195154) است. #به <محدوده><عمل>هایش نگاه میکند. اول و فقط یکی است # # #شماره سطر در محدوده است، پس عمل را اجرا میکند: #+به تعویض کردن بلندترین رشته در سطر که با یک فاصله #پایان یافته ("0000000 ")، با هیچ (//) اقدام میکند، #و اگر موفق شود نتیجه را چاپ میکند (در اینجا p یک #+نشانگر جهت فرمان s است، با فرمان p تفاوت دارد). #اکنون sed آماده ادامه خواندن ورودیاش میباشد (توجه #+کنید که اگر گزینه -n داده نشده بود sed قبل از #+ادامه، یکبار دیگر سطر را چاپ کرده بود). #اکنون، sed باقیمانده کاراکترها را میخواند، و انتهای #+فایل را تشخیص میدهد. #حال آماده پردازش سطر دوم خوانده شده است (که با $ به #+عنوان آخرین سطر شمارهدار است). #مشاهده میکند با هیچ <محدوده>ای منطبق نیست، بنابراین #+کارش انجام گردیده است. #به طور خلاصه این فرمان sed یعنی: #«فقط در سطر اول، هر کاراکتری تا رسیدن به سمت راستترین #+فاصله را حذف کرده، آنوقت آن را چاپ نماید.» #روش مناسبتری برای انجام این کار میتوانست چنین باشد: # #در اینجا، دو <محدوده><عمل> (میتواند #نوشته شود sed -e 's/.* //' -e q): # # # #در اینجا، sed فقط اولین سطر ورودیاش را میخواند. هر دو #عمل را انجام میدهد، و قبل از خروج سطر(جایگزین شده) را #+(به دلیل عمل q) چاپ میکند، چون گزینه -n داده نشده. # #یک جایگزین سادهتر برای اسکریپت یک سطری فوق، این است: # exit
سطرهای انتهای یک فایل را در stdout لیست میکند. پیشفرض آن 10 سطر است، اما میتواند با گزینه -n تغییر کند. به طور معمول برای پیگردی تغییرات یک فایل ثبت وقایع سیستم، با گزینه -f به کار میرود، که سطرهای پیوست شده به فایل را بیرون میدهد.
مثال 16-15. کاربرد tail برای دیدهبانی ثبت وقایع سیستم
#!/bin/bash filename=sys.log cat /dev/null > $filename; echo "Creating / cleaning out file." #اگر فایل از قبل وجود نداشته باشد آن را ایجاد میکند، #+و اگر موجود باشد آن را به طول صفر کوتاه میکند. #: > filename و > filename نیز کار میکند. tail /var/log/messages > $filename #برای این کار مجوز خواندن /var/log/messages باید همگانی باشد. echo "$filename contains tail end of system log." exit 0
برای لیست کردن یک سطر خاصِ یک فایل متن، خروجی فرمان head را به فرمان tail -n 1 لولهکشی کنید. برای مثال، head -n 8 database.txt | tail -n 1 سطر هشتم از فایل database.txt را لیست میکند. برای تنظیم یک متغیر به یک بلوک مفروض از یک فایل متن: var=$(head -n $m $filename | tail -n $n) # # # |
پیادهسازیهای جدیدتر tail کاربرد قدیمیتر tail -$LINES filename را ناپسند میدانند. tail -n $LINES filename استاندارد، صحیح است. |
همچنین مثال 16-5، مثال 16-39 و مثال 32-6 را مشاهده نمایید.
یک ابزار جستجوی فایل چند منظوره است که عبارتهای منظم را به کار میبرد. در آغاز یک فرمان-فیلتر در ویرایشگر خطی قدیمی و پر ارزش ed بود: g/re/p از global - regular expression - print اخذ گردیده است.
grep pattern [file...]
فایل(های) مقصد را برای موارد پیدایش pattern جستجو میکند، که در آن pattern میتواند متن لفظی یا عبارت منظم باشد.bash$ grep '[rst]ystem.$' osinfo.txt The GPL governs the distribution of the Linux operating system.
اگر فایل(های) مقصد تعیین نشده باشد، grep به صورت یک فیلتر بر روی stdout عمل میکند، همچنانکه در یک pipe عمل میکند.
bash$ ps ax | grep clock 765 tty1 S 0:00 xclock 901 pts/1 S 0:00 grep clock
گزینه -i موجب جستجوی حساس به حالت حروف میگردد.
گزینه -w فقط کلمههای کامل را مطابقت میدهد.
گزینه -l فقط فایلهایی را که در آنها مورد انطباقی پیدا شده باشد، لیست میکند، اما سطرهای انطباق را لیست نمیکند.
گزینه -r (بازگشت) فایلهای دایرکتوری کاری جاری و تمام دایرکتوریهای فرعی تحت آن را جستجو مینماید.
گزینه -n سطرهای انطباق را به همراه شماره سطرها لیست میکند.
bash$ grep -n Linux osinfo.txt 2:This is a file containing information about Linux. 6:The GPL governs the distribution of the Linux operating system.
گزینه -v (یا --invert-match) موارد انطباق را فیلتر میکند.
grep pattern1 *.txt | grep -v pattern2 #تمام سطرهای فایلهای "*.txt" را که شامل "pattern1" باشند، #اما شامل "pattern2" «نباشند»، لیست میکند.
گزینه -c (--count) به جای لیست واقعی موارد انطباق، شمارش عددی مطابقتها را ارایه میکند.
grep -c txt *.sgml #(تعداد موارد وجود txt در فایلهای *.sgml) # #نقطه ^ #یعنی شمارش (-c) موارد جداشده با بایت صفر (-z) منطبق با "." #یعنی سطرهایی که تهی نیستند (شامل حداقل یک کارکتر هستند). # printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz . # printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz '$' # printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz '^' # # printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -c '$' # #به طور پیشفرض، کاراکترهای سطرجدید (\n) اقلام را جهت انطباق جدا میکنند. #توجه نمایید که گزینه -z مختص grep گنو است. #با تشکر از S.C.
گزینه --color (یا --colour) رشته انطباق را به صورت رنگی علامت میزند (در کنسول یا در یک پنجره xterm). چون grep هر سطر کامل شامل الگوی انطباق را بیرون میدهد، این به شما امکان میدهد به طور دقیق آنچه را که مطابقت داده میشود مشاهده نمایید. همچنین گزینه -o را که فقط قسمت منطبقِ سطر(ها) را نشان میدهد، ملاحظه نمایید.
مثال 16-16. نمایش دادن سطرهای From در یک لیست مرتبشده پیغامهای e-mail
#!/bin/bash # #برنامه سودمند 'from' در سولاریس، BSD وغیره را شبیهسازی مینماید. #سطر سرآیند "From" تمام پیغامهای دایرکتوری ایمیل شما را بازتاب میدهد. MAILDIR=~/mail/* #نقلقول نکردن متغیر. چرا؟ #احتمالا کنترل که آیا $MAILDIR موجود است: . . . if [ -d $MAILDIR ] GREP_OPTS="-H -A 5 --color" #نمایش فایل، بعلاوه سطرهای اضافی متن #+و نشان دادن "From" به صورت رنگی. TARGETSTR="^From" #"From" در ابتدای سطر. for file in $MAILDIR #نقلقول نکردن متغیر. do grep $GREP_OPTS "$TARGETSTR" "$file" # #یکبار دیگر، این متغیر را نقلقول نکنید. echo done exit $? #ممکن است مایل باشید خروجی این اسکریپت را به 'more' لولهکشی #+نمایید، یا آن را به یک فایل تغییر مسیر بدهید . . .
grep موقعی که با بیش از یک فایل مقصد معین فراخوانی شده باشد، مشخص میکند که کدام فایل شامل موارد انطباق است.
bash$ grep Linux osinfo.txt misc.txt osinfo.txt:This is a file containing information about Linux. osinfo.txt:The GPL governs the distribution of the Linux operating system. misc.txt:The Linux operating system is steadily gaining in popularity.
موقع جستجوی فقط یک فایل مقصد، برای وادار نمودن grep به نمایش نام فایل، به سادگی /dev/null را به عنوان فایل دوم به آن بدهید. bash$ grep Linux osinfo.txt /dev/null osinfo.txt:This is a file containing information about Linux. osinfo.txt:The GPL governs the distribution of the Linux operating system. |
اگر یک انطباق موفق وجود داشته باشد، grep یک وضعیت خروج 0 برگشت میدهد، که مخصوصاً در آمیزش با گزینه -q جهت موقوف نمودن خروجی، آنرا برای بررسی یک شرط در اسکریپت سودمند میسازد.
SUCCESS=0 #اگر جستجوی grep موفق باشد word=Linux filename=data.file grep -q "$word" "$filename" #گزینه -q باعث میشود چیزی در خروجی منعکس نگردد if [ $? -eq $SUCCESS ] #if grep -q "$word" "$filename" میتواند جایگزین سطرهای 5 تا 7 بشود. then echo "$word found in $filename" else echo "$word not found in $filename" fi
مثال 32-6 چگونگی به کار بردن grep را برای جستجوی یک الگوی کلمه در فایل ثبت رخداد سیستم نمایش میدهد.
مثال 16-17. شبیهسازی grep در یک اسکریپت
#!/bin/bash # E_BADARGS=85 if [ -z "$1" ] # then echo "Usage: `basename $0` pattern" exit $E_BADARGS fi echo for file in * # do output=$(sed -n /"$1"/p $file) # if [ ! -z "$output" ] #اگر "$output" نقلقولی نباشد چه میشود؟ then echo -n "$file: " echo "$output" fi #sed -ne "/$1/s|^|${file}: |p" معادل مورد فوق است. echo done echo exit 0 # # #(1 افزودن تعویض سطر به خروجی، اگر در فایل(ها)، بیش از یک مورد انطباق باشد. #(2 افزودن ویژگیها.
چگونه grep میتواند برای دو (یا بیشتر) الگوی جداگانه جستجو نماید؟ اگر شما بخواهید grep تمام سطرهای یک فایل یا فایلهایی را که شامل هر دو الگوی "pattern1" و "pattern2" هستند نمایش بدهد چطور؟
یک روش لولهکشی نتیجه grep pattern1 به grep pattern2 است.
برای مثال، فایل زیر معلوم است:
# This is a sample file. This is an ordinary text file. This file does not contain any unusual text. This file is not unusual. Here is some text.
اکنون، بیایید این فایل را برای سطرهای شامل هر دو کلمه «file» و «text» جستجو کنیم . . .
bash$ grep file tstfile # Filename: tstfile This is a sample file. This is an ordinary text file. This file does not contain any unusual text. This file is not unusual. bash$ grep file tstfile | grep text This is an ordinary text file. This file does not contain any unusual text.
اکنون یک سرگرمی جالب با استفاده از grep . . .
مثال 16-18. حل کننده پازل جدول کلمات
#!/bin/bash # #در واقع این یک لفاف در اطراف یک کد تکسطری است (سطر 46). #بازی حلکننده پازل جدول کلمات و تحریف لغت. #شما «بعضی» از حروف در یک کلمه را که در جستجوی آن هستید، میدانید #+بنابراین به لیستی از تمام کلمات معتبر شامل حروف شناخته در محلهای #+معین، احتیاج دارید. #برای مثال: w...i....n # #w در موقعیت 1، 3 حرف ناشناخته، i در مکان پنجم، 4 ناشناخته، n در انتها. #(توضیحات در انتهای اسکریپت را ملاحظه کنید.) E_NOPATT=71 DICT=/usr/share/dict/word.lst # #لیست کلمههای ASCII، یک کلمه در هر سطر. #اگر شما به یک لیست مناسب احتیاج دارید، بسته لیست #+کلمات "yawl" نگارنده در آدرس زیر را دانلود نمایید. # # # if [ -z "$1" ] #اگر الگوی کلمه به عنوان یک شناسه then #+خط فرمان تعیین نگردیده است . . . echo #+ echo "Usage:" #+پیغام نحوه کاربرد. echo echo ""$0" \"pattern,\"" echo "where \"pattern\" is in the form" echo "xxx..x.x..." echo echo "The x's represent known letters," echo "and the periods are unknown letters (blanks)." echo "Letters and periods can be in any position." echo "For example, try: sh cw-solver.sh w...i....n" echo exit $E_NOPATT fi echo # # grep ^"$1"$ "$DICT" # # #^ مهار شروع کلمه عبارت منظم است. #$ مهار پایان کلمه عبارت منظم است. #From _Stupid Grep Tricks، جلد اول، کتابی از #+مولف راهنمای ABS که ممکن است باز هم فرصتی برای #+نوشتن به دست آورد . . . یکی از این روزها . . . # echo exit $? # # #+bash$ sh cw-solver.sh w...i....n wellington workingman workingmen
egrep -- grep توسعهیافته -- همانند grep -E است. این فرمانِ تا اندازهای متفاوت، از مجموعه توسعهیافته عبارتهای منظم استفاده میکند، که میتواند جستجو را مقداری قابل انعطافتر نماید. همچنین استفاده از عملگر بولی | (یا) را مجاز میکند.
bash $ egrep 'matches|Matches' file.txt Line 1 matches. Line 3 Matches. Line 4 contains matches, but also Matches
fgrep -- grep سریع -- همانند egrep -F است. یک جستجوی لفظی رشته (نه عبارتهای منظم) انجام میدهد، که به طورکلی مقدار کمی به کارها سرعت میبخشد.
در برخی توزیعهای لینوکس، egrep و fgrep پیوندهای نمادین یا مستعارهایی برای grep ، اما به ترتیب فراخوانی شده با گزینههای -E و -F هستند. |
مثال 16-19. جستجوی تعریفها در فرهنگ لغت Webster's 1913
#!/bin/bash # #این اسکریپت تعریفها را در فرهنگ لغت 1913 Webster جستجو میکند. #این فرهنگ لغت همگانی در سایتهای مختلفی جهت دانلود در دسترس است، #+از جمله پروژه گوتنبرگ (http://www.gutenberg.org/etext/247). # #قبل از به کار بردن آن با این اسکریپت، آن را از قالب DOS به UNIX #+(فقط کاراکتر LF در انتهای سطر) تبدیل نمایید. #فایل را در قالب متن اسکی ساده متراکم نشده ذخیره کنید. #متغیر DEFAULT_DICTFILE پایین را به مسیر حضور فایل تنظیم نمایید. E_BADARGS=85 MAXCONTEXTLINES=50 # DEFAULT_DICTFILE="/usr/share/dict/webster1913-dict.txt" # # # # #در این ویرایش خاص از 1913 Webster #+هر مدخل با یک حرف uppercase شروع میشود #+(حروف کوچک برای بقیه کاراکترها). #فقط «سطر اول واقعی» هر مدخل به این صورت #+شروع میشود، و بدین علت الگوریتم جستجوی #پایین کار میکند. if [[ -z $(echo "$1" | sed -n '/^[A-Z]/p') ]] # #+ then echo "Usage: `basename $0` Word-to-define [dictionary-file]" echo echo "Note: Word to look up must start with capital letter," echo "with the rest of the word in lowercase." echo "--------------------------------------------" echo "Examples: Abandon, Dictionary, Marking, etc." exit $E_BADARGS fi if [ -z "$2" ] # #+ then dictfile=$DEFAULT_DICTFILE else dictfile="$2" fi # Definition=$(fgrep -A $MAXCONTEXTLINES "$1 \\" "$dictfile") # # #بله، fgrep برای جستجوی حتی یک فایل متن بزرگ به حد کافی سریع است # echo "$Definition" | sed -n '1,/^[A-Z]/p' | # sed '$d' | sed '$d' # # exit $? # # #(1 اسکریپت را برای پذیرش هر نوع ورودی الفبایی #(حروف بزرگ، کوچک، و متداخل) و تبدیل آن به #قالب مورد قبول برای پردازش، ویرایش کنید. # #(2 با استفاده از چیزی مانند gdialog یا zenity و غیره #اسکریپت را به یک برنامه کاربردی GUI تبدیل کنید #آنوقت، اسکریپت دیگر شناسه یا شناسههای خط فرمان #قبول نخواهد کرد. # #(3 اسکریپت را برای تجزیه یکی دیگر از فرهنگهای همگانی #از قبیل U.S. Census Bureau Gazetteer ویرایش کنید.
همچنین برای یک نمونه از جستجوی سریع fgrep روی یک فایل متن بزرگ، مثال A-41 را مشاهده نمایید. |
agrep (approximate grep) تواناییهای grep را به انطباق تقریبی گسترش میدهد. رشته جستجو ممکن است بواسطه تعداد معینی از کاراکترها با انطباقهای حاصله تفاوت داشته باشد. این برنامه سودمند، بخشی از هسته مرکزی توزیع لینوکس نیست.
برای جستجوی فایلهای فشرده، zgrep، zegrep، یا zfgrep را به کار ببرید. اینها روی فایلهای غیرفشرده نیز کار میکنند، اگرچه آهستهتر از grep، egrep، fgrep ساده. آنها برای جستجو در میان یک مجموعه مختلط فایلها، برخی فشرده و بعضی غیر فشرده، سودمند هستند. برای جستجو در فایلهای bzip شده، از bzgrep استفاده نمایید. |
فرمان look مانند grep کار میکند، اما جستجویی روی یک «فرهنگ لغت»، یک لیست مرتبشده کلمات، انجام میدهد. به طور پیشفرض، look جهت یک انطباق در /usr/dict/words جستجو میکند، اما یک فایل فرهنگ لغت متفاوت نیز میتواند تعیین بشود.
مثال 16-20. کنترل کلمات در یک لیست برای تصدیق اعتبار
#!/bin/bash # file=words.data # echo echo "Testing file $file" echo while [ "$word" != end ] do # # read word # look $word > /dev/null # #لغات را در فایل /usr/share/dict/words جستجو میکند. #+(که معمولاً یک پیوند به فایل linux.words است). lookup=$? #وضعیت خروج فرمان look. if [ "$lookup" -eq 0 ] then echo "\"$word\" is valid." else echo "\"$word\" is invalid." fi done <"$file" #stdin را به $file تغییر مسیر میدهد، بنابراین از اینجا میخواند. echo exit 0 # #به علت فرمان exit فوق، کد زیر اجرا نمیشود. #Stephane Chazelas جایگزین مختصرتر پایین را پیشنهاد میکند: while read word && [[ $word != end ]] do if look "$word" > /dev/null then echo "\"$word\" is valid." else echo "\"$word\" is invalid." fi done <"$file" exit 0
زبانهای اسکریپتنویسی بویژه مناسب برای تجزیه فایلهای متن و خروجی فرمان. میتوانند به تنهایی یا با یکدیگر در لولهها و اسکریپتهای پوسته تعبیه بشوند.
«ویرایشگر جریانی» غیر محاورهای، به کار بردن بسیاری از فرمانهای ex را در وضعیت دستهای مجاز میکند. در اسکریپتهای پوسته مورد استفاده بسیاری پیدا میکند.
استخراج کننده و قالبدهنده فایل قابل برنامهنویسی، مناسب برای دستکاری و/یا استخراج فیلدها (ستونها) در فایلهای متن ساختیافته. ترکیب دستوری آن مشابه با زبان C است.
wc یک «شمارش کلمه» بر روی فایل یا جریان ورودی-خروجی ارایه میکند:
bash $ wc /usr/share/doc/sed-4.1.2/README 13 70 447 README [13 lines 70 words 447 characters]
wc -w فقط شمارش کلمات را ارایه میکند.
wc -l فقط شمارش سطر را ارایه میکند.
wc -c فقط شمارش بایت را ارایه میکند.
wc -m فقط شمارش کاراکتر را ارایه میکند.
wc -L فقط طول بلندترین سطر را ارایه میکند.
کاربرد wc برای شمردن آن که چند فایل .txt در دایرکتوری کاری جاری وجود دارد:
$ ls *.txt | wc -l #به شرط اینکه هیچ یک از فایلهای *.txt دارای سطر جدید #+ #روشهای جایگزین انجام این کار عبارتند از: # # #با تشکر از S.C.
استفاده از wc برای جمع زدن اندازه فایلهایی که نامشان با حروف محدوده d - h شروع میشود:
bash$ wc [d-h]* | grep total | awk '{print $3}' 71832
استفاده از wc برای شمردن موارد حضور کلمه «Linux» در فایل منبع اصلی این کتاب.
bash$ grep Linux abs-book.sgml | wc -l 138
همچنین مثال 16-39 و مثال 20-8 را مشاهده نمایید.
برخی فرمانها، قابلیتهایی از wc را به صورت گزینه در خود دارند.
... | grep foo | wc -l #این ساختار مورد استفاده مکرر، میتواند به طور خلاصهتری ارایه شود. ... | grep -c foo #فقط با استفاده از گزینه -c (یا --count) برنامه grep. #با تشکر از S.C.
فیلتر ترجمه کاراکتر.
باید از نقلقول و/یا براکتها، به طور مناسب استفاده شود. نقلقولهاپوسته را از تفسیر کاراکترهای خاص در رشتههای فرمان tr باز میدارند. براکتها برای پیشگیری از بسط یافتن توسط پوسته، باید نقلقولی بشوند. |
هر کدام از tr "A-Z" "*" <filename یا tr A-Z \* <filename تمام حروف بزرگ در filename را به ستاره تغییر میدهند (در stdout مینویسند). این ممکن است در برخی سیستمها کار نکند، اما tr A-Z '[**]' کار میکند.
گزینه -d کاراکترهای یک محدوده را حذف میکند.
echo "abcdef" # echo "abcdef" | tr -d b-d # tr -d 0-9 <filename #تمام ارقام را از فایل filename حذف میکند.
گزینه --squeeze-repeats (یا -s) غیر از مورد اول، بقیه کاراکترها در رشتهای از کاراکترهای متوالی
bash$ echo "XXXXX" | tr --squeeze-repeats 'X' X
گزینه -c (complement) مجموعه کاراکتر برای انطباق را وارونه میکند. با این گزینه، فرمان tr فقط بر روی آن کاراکترهایی که با مجموعه مشخص شده مطابقت نمیکنند، عمل مینماید.
bash$ echo "acfdeb123" | tr -c b-d + +c+d+b++++
توجه نمایید که tr کلاسهای کاراکتر POSIX را تشخیص میدهد.[1]
bash$ echo "abcd2ef1" | tr '[:alpha:]' - ----2--1
مثال 16-21. toupper: تبدیل تمام کاراکترهای یک فایل به حروف بزرگ.
#!/bin/bash #یک فایل را تماماً به حروف بزرگ تغییر میدهد. E_BADARGS=85 if [ -z "$1" ] # then echo "Usage: `basename $0` filename" exit $E_BADARGS fi tr a-z A-Z <"$1" #همان نتیجه بالا، اما با استفاده ازنشانهگذاری مجموعه کاراکتر POSIX: # #با تشکر از S.C. #یا حتی . . . # #یا یک دوجین روشهای دیگر . . . exit 0 # # #+ #اشاره: از یکی از فرمانهای case یا select استفاده کنید.
مثال 16-22. lowercase: نام تمام فایلها در دایرکتوری کاری را به حروف کوچک تبدیل میکند.
#!/bin/bash # # # #الهام گرفته از اسکریپت نوشته John Dubois، که به وسیله #+Chet Ramey به داخل Bash منتقل گردیده بود، و به طور #+قابل ملاحظهای توسط نگارنده راهنمای ABS سادهسازی گردیده. for filename in * # do fname=`basename $filename` n=`echo $fname | tr A-Z a-z` # if [ "$fname" != "$n" ] # then mv $fname $n fi done exit $? #به علت exit فوق، کد زیر این سطر اجرا نخواهد گردید. # #برای اجرای آن، اسکریپت بالای سطر را حذف کنید. #اسکریپت فوق روی نامفایلهای شامل فاصله و سطرجدید عمل نخواهد کرد. #بدین علت Stephane Chazelas جایگزین پایین را پیشنهاد میکند: for filename in * #نیازی به استفاده از basename نیست، #چون * هیچ نام فایل شامل / را برگشت نمیدهد. do n=`echo "$filename/" | tr '[:upper:]' '[:lower:]'` #نشانهگذاری مجموعه کاراکتر POSIX #کاراکتر / اضافه شده است برای اینکه سطرهای #جدید دنباله با جایگزینی فرمان حذف نشوند. #جایگزینی متغیر: n=${n%/} #/ اضافه شده فوق از آخر نام فایل حذف میشود. [[ $filename == $n ]] || mv "$filename" "$n" #کنترل میکند آیا نام فایل از قبل حروف کوچک است. done exit $?
مثال 16-23. du: تبدیل فایل متن DOS به یونیکس.
#!/bin/bash # E_WRONGARGS=85 if [ -z "$1" ] then echo "Usage: `basename $0` filename-to-convert" exit $E_WRONGARGS fi NEWFILENAME=$1.unx CR='\015' # #015 مقدار اکتال کد اسکی CR است. #سطرها در فایل متن DOS به CR-LF ختم میشوند. #سطرها در فایل متن یونیکس فقط به LF ختم میشوند. tr -d $CR < $1 > $NEWFILENAME #حذف CRها و نوشتن فایل جدید. echo "Original DOS text file is \"$1\"." echo "Converted UNIX text file is \"$NEWFILENAME\"." exit 0 # # #اسکریپت فوق را برای تبدیل از یونیکس به DOS تغییر بدهید.
مثال 16-24. rot13: رمزیسازی فوق ضعیف.
#!/bin/bash #rot13.sh: الگوریتم رمزدار کردن rot13 کلاسیک، که # #نحوه استعمال: ./rot13.sh filename #یا ./rot13.sh <filename #یا ./rot13.sh و ارایه ورودی از صفحه کلید cat "$@" | tr 'a-zA-Z' 'n-za-mN-ZA-M' #تبدیل a به n، و b به o و ... #ساختار cat "$@" دریافت ورودی از فایل یا از stdin را اجازه میدهد. exit 0
مثال 16-25. تولید پازلهای «Crypto-Quote»
#!/bin/bash # #نقلقولهای معروف را با یک جایگزینی الفبایی واحد، رمزی خواهد نمود. #نتیجه مشابه پازلهای «Crypto Quote» مشاهده شده در صفحههای Op Ed #+در روزنامه Sunday است. key=ETAOINSHRDLUBCFGJMQPVWZYXK #«key» چیزی بیشتر از یک الفبای بهم ریخته نیست. #تغییر دادن «key» رمز را تغییر میدهد. #ساختار cat "$@" ورودی را یا از stdin یا از فایلها دریافت میکند. #اگر از stdin استفاده میکنید، ورودی را با یک Control-D خاتمه دهید. #در غیر اینصورت، نام فایل را به عنوان شناسه خط فرمان مشخص نمایید. cat "$@" | tr "a-z" "A-Z" | tr "A-Z" "$key" # #روی نقلقولها با حروف کوچک، حروف بزرگ، یا حالت مختلط عمل میکند. #کاراکترهای غیر الفبایی داده شده، بدون تغییر میمانند. #این اسکریپت را با چیزی مشابه مورد زیر امتحان کنید: # # # #خروجی عبارت است از: # # #برای شکستن رمز: # #این رمز ساده لوحانه میتواند توسط یک نوجوان 12 ساله فقط #+با استفاده از مداد و کاغذ شکسته شود. exit 0 # # #اسکریپت را برای انجام رمزنگاری یا رمزگشایی بر اساس #+شناسه(های) خط فرمان، ویرایش کنید.
البته، tr برای مبهم نمودن کد مفید است.
#!/bin/bash # x="wftedskaebjgdBstbdbsmnjgz" echo $x | tr "a-z" 'oh, turtleneck Phrase Jar!' #مبتنی بر مبحث "Just another Perl hacker" ویکیپدیا.
فیلتری که سطرهای ورودی را به عرض تعیین شده میشکند. این فیلتر مخصوصاً با گزینه -s مفید است، که سطرها را از فاصله کلمات میشکند (مثال 16-26 و مثال A-1 را ببینید).
قالبدهنده فایل بیاستعداد، مورد استفاده در یک لوله برای «wrap» سطرهای بلند متن خروجی.
مثال 16-26. لیست فایل قالببندی شده.
#!/bin/bash WIDTH=40 #عرض 40 برای ستونها b=`ls /usr/local/bin` # echo $b | fmt -w $WIDTH #با این کد نیز میتوانست انجام بشود: # exit 0
همچنین مثال 16-5 را مشاهده کنید.
یک جایگزین قدرتمند fmt برنامه سودمند Kamil Toman به نام par است، که در http://www.cs.berkeley.edu/~amc/Par/ قابل دسترس است. |
این فیلترِ دارای نام گمراهکننده، تعویض سطرهای معکوس را از یک جریان ورودی حذف مینماید. همچنین سعی میکند فضای سفید را با tabهای معادل تعویض کند. مورد استفاده اصلی col در فیلتر کردن خروجی برخی برنامههای ویرایشگر متن، از قبیل groff و tbl است.
قالبدهنده ستون. این فیلتر، خروجی متن فهرست مانند را از طریق درج tab در محلهای مناسب، به یک جدول «چاپی شکیل» تبدیل می کند.
مثال 16-27. به کار بردن column برای قالببندی یک فهرست دایرکتوری
#!/bin/bash # #یک بهبود بخشی اندک در مثال صفحه man فرمان column. (printf "PERMISSIONS LINKS OWNER GROUP SIZE MONTH DAY HH:MM PROG-NAME\n" \ ; ls -l | sed 1d) | column -t # #sed 1d در لوله اولین سطر خروجی را که "total N" خواهد بود، و در #+آن N اندازه کل فایلهای پیدا شده توسط "ls -l" است، حذف میکند. #گزینه -t با column یک جدول شکیل چاپ میکند. exit 0
فیلتر پاک کننده ستون. این فیلتر، ستونها (کاراکترها) را از یک فایل حذف میکند و فایل را بدون ستونهای حدفاصل معین شده، در stdout مینویسد. colrm 2 4 <filename کاراکترهای ستون دوم، سوم، و چهارم را از هر سطر فایل متن filenameحذف میکند.
اگر فایل شامل tabها یا کاراکترهای غیرقابل چاپ باشد، این ممکن است موجب رفتار پیشبینی نشده بشود. در چنین موردی، به کار بردن expand و unexpand در یک لوله مقدم بر colrm را در نظر بگیرید. |
فیلتر شمارهگذاری سطر: nl filename محتوای فایل filename را در stdout لیست میکند، اما شمارههای ترتیبی را در ابتدای هر سطر غیر خالی اضافه میکند. اگر filename ذکر نشده باشد، روی stdin عمل میکند.
خروجی nl بسیار مشابه cat -b است، چون طبق قرارداد nl سطرهای خالی را شمارهگذاری نمیکند.
مثال 16-28. nl: یک اسکریپت خود شمارهگذار.
#!/bin/bash # #این اسکریپت دوبار خودش را با سطرهای شمارهگذاری شدهاش در stdout بازتاب میدهد. echo " line number = $LINENO" #nl این سطر را به عنوان سطر شماره 4 میبیند #(nl سطرهای خالی را شمارهگذاری نمیکند). #cat -n به درستی آن را سطر شماره 6 میبیند. nl `basename $0` echo; echo #اکنون، اجازه بدهید با cat -n امتحان کنیم. cat -n `basename $0` #تفاوت در آن است که cat -n سطرهای خالی را شمارهگذاری میکند. #توجه داشته باشید که nl -ba نیز همینطور عمل خواهد کرد. exit 0 #----------------------------------------------------------
فیلتر قالببندی چاپ. این فیلتر فایلها (یا stdout) را به بخشهای مناسب برای چاپ نسخه کاغذی یا مشاهده روی صفحه نمایش صفحهبندی میکند. گزینههای متنوعی، دستکاری سطر و ستون، اتصال سطرها، تنظیم کنارهها، شمارهگذاری سطرها، افزودن سر صفحهها، الحاق فایلها و موارد بسیار دیگری را میسر میکنند. فرمان pr بسیاری از تواناییهای nl، paste، fold، column، و expand را درهم میآمیزد.
pr -o 5 --width=65 fileZZZ | more یک لیست صفحهبندی شده زیبا از fileZZZ با کنارههای تنظیم شده با 5 و 65 در صفحه نمایش ارایه میکند.
یک گزینه بویژه سودمند، گزینه -d است، که نگارش یک خط در میان (همانند نتیجه sed -G) را تحمیل میکند.
بسته gettext گنو مجموعهای از برنامههای سودمند برای بومیسازی و ترجمه متن خروجی برنامهها به زبانهای خارجی است. درحالیکه در آغاز برای برنامههای C در نظر گرفته شد، اکنون تعدادی از زبانهای برنامهنویسی و اسکریپتنویسی را به طور کامل پشتیبانی میکند.
برنامه gettext روی اسکرپتهای پوسته عمل میکند. صفحه info را مشاهده کنید.
برنامهای برای تولید فهرست مشخصات پیغامهای باینری. برای محلیکردن مورد استفاده است.
برنامه سودمندی برای تبدیل فایل(ها) به یک encoding (مجموعه کاراکتر) متفاوت. استفاده اصلی آن در محلیسازی است.
#تبدیل یک رشته از UTF-8 به UTF-16 و چاپ در BookList function write_utf8_string { STRING=$1 BOOKLIST=$2 echo -n "$STRING" | iconv -f UTF8 -t UTF16 | \ cut -b 3- | tr -d \\n >> "$BOOKLIST" } #از اسکریپت "booklistgen.sh" نوشته Peter Knowle #+برای تبدیل فایلها به قالب Sony Librie/PRS-50X. #
این را به عنوان یک نگارشِ تفننیتر iconv فوق در نظر بگیرید. این برنامه سودمندِ بسیار فراگیرندهای برای تبدیل فایل به یک طرح encoding متفاوت است. توجه داشته باشید که recode بخشی از استاندارد نصب لینوکس نیست.
TeX و Postscript زبانهای نشانهگذاری متن هستند که برای آمادهسازی نسخه جهت چاپ یا نمایش تصویری قالببندی شده استفاده میشوند.
TeX سیستم حروفچینی استادانه Donald Knuth است. بیشتر اوقات نوشتن یک اسکریپت پوسته کپسول کننده تمام گزینهها و شناسههای داده شده به یکی از این زبانهای نشانهگذاری، مناسب است.
Ghostscript (gs) مفسر Postscript گنو است.
برنامه سودمندی برای پردازش فایلهای TeX و pdf. در اکثر توزیعهای لینوکس در /usr/bin قرار دارد، در واقع یک روکش ( wrapper) پوسته است که Perl را برای فراخوانی نمودن Tex احضار میکند.
texexec --pdfarrange --result=Concatenated.pdf *pdf #تمام فایلهای pdf در دایرکتوری کاری جاری را در یک فایل بههم پیوسته #+با نام Concatenated.pdf با یکدیگر ادغام میکند. . . #( گزینه --pdfarrange یک فایل pdf را دوباره صفحهبندی میکند.) #+گزینه --pdfcombine را نیز ببینید. #سطر فرمان فوق میتواند پارامتر دار شده و در یک اسکریپت پوسته قرار بگیرد.
برنامه سودمندی برای تبدیل فایلهای متن ساده به PostScript
برای مثال، enscript filename.txt -p filename.ps فایل خروجی PostScript به نام filename.ps را تولید میکند.
یک زبان دیگر نمایش شکیل و علامتگذاری شده متن، groff است. این یک نگارش ارتقاء یافته گنو از بسته حروفچینی و نمایش roff/troff یونیکس ارجمند است. صفحههای Man از groff استفاده میکنند.
برنامه سودمند پردازش جدول tbl بخش پر اهمیتی از groff است، که عملکرد آن تبدیل جدول نشانهدار به فرمانهای groff است.
برنامه سودمند پردازش معادله eqn نیز بخشی از groff است، و کارآیی آن در تبدیل معادله نشانهدار به فرمانهای groff است.
مثال 16-29. manview: نمایش صفحههای man قالبدار
#!/bin/bash # #این اسکریپت موقع نوشتن source صفحه man مفید است. #به شما اجازه میدهد در حالیکه روی صفحه کار میکنید، نتایج را #+به طور درجا مشاهده کنید. E_WRONGARGS=85 if [ -z "$1" ] then echo "Usage: `basename $0` filename" exit $E_WRONGARGS fi # groff -Tascii -man $1 | less #از صفحه man برای groff. # #اگر صفحه man شامل جدولها و/یا معادلهها باشد، #+آنوقت کد فوق، بالا میآورد. #سطر زیر میتواند چنین مواردی را مدیریت نماید. # # # #با تشکر از S.C. exit $? #اسکریپت maned.sh را نیز ملاحظه نمایید.
همچنین مثال A-39 را مشاهده کنید.
تحلیلکننده واژهای lex برنامههایی برای انطباق الگو ارایه میکند. این تحلیلکننده در سیستمهای لینوکس با flex انحصاری نشده، تعویض گردیده است.
برنامه سودمند yacc یک تجزیهکننده مبتنی بر مجموعهای از مشخصات تولید میکند. این برنامه نیز در سیستمهای لینوکس با bison غیر انحصاری، تعویض گردیده است.
[1] | این فقط برای نگارش گنوی tr صحیح است، نه برای نگارش عمومی که اغلب روی سیستمهای یونیکس تجارتی یافت میشود. |