نگارشهای جدیدتر Bash آرایههای یک بعدی را پشتیبانی میکنند. عناصر آرایه میتوانند با به کار بردن نماد variable[xx] ارزشگذاری بشوند. به طور جایگزین، یک اسکریپت ممکن است تمام آرایه را به وسیله یک دستورالعمل صریح declare -a variable معرفی نماید. برای مراجعه به (بازیابی محتویات)یک عنصر آرایه، نشانهگذاری براکتهای کمانی، ${element[xx]} را به کار ببرید.
مثال 27-1. کاربرد آرایه ساده
#!/bin/bash area[11]=23 area[13]=37 area[51]=UFOs #لازم نیست عناصر آرایه متوالی یا همجوار باشند. #برخی عناصر آرایه میتوانند ارزش گذاری نشده بمانند. #شکاف بین عناصر مورد قبول است. #در حقیقت، آرایهها با دادههای پراکنده (آرایههای پراکنده) #+در نرمافزار پردازش صفحه گسترده سودمند هستند. echo -n "area[11] = " echo ${area[11]} #{براکتهای کمانی } لازم است. echo -n "area[13] = " echo ${area[13]} echo "Contents of area[51] are ${area[51]}." #محتویات متغیر آرایه ارزشگذاری نشده خالی چاپ میشود (متغیر تهی). echo -n "area[43] = " echo ${area[43]} echo "(area[43] unassigned)" echo #حاصل جمع دو عضو آرایه به سومی تخصیص داده شده area[5]=`expr ${area[11]} + ${area[13]}` echo "area[5] = area[11] + area[13]" echo -n "area[5] = " echo ${area[5]} area[6]=`expr ${area[11]} + ${area[51]}` echo "area[6] = area[11] + area[51]" echo -n "area[6] = " echo ${area[6]} #این ناموفق است، زیرا اضافه کردن یک عدد صحیح به یک رشته جایز نیست. echo; echo; echo #----------------------------------------------------------------- #یک آرایه دیگر، area2 #یک روش دیگر تخصیص متغیرهای آرایهای... #array_name=( XXX YYY ZZZ ... ) area2=( zero one two three four ) echo -n "area2[0] = " echo ${area2[0]} #پس اینطور، شاخصگذاری از صفر (عنصر اول آرایه [0] است نه [1]). echo -n "area2[1] = " echo ${area2[1]} #[1] عنصر دوم آرایه است. #----------------------------------------------------------------- echo; echo; echo #----------------------------------------------- #بازهم یک آرایه دیگر، area3 #بازهم یک روش دیگر تخصیص متغیرهای آرایهای... #array_name=([xx]=XXX [yy]=YYY ...) area3=([17]=seventeen [24]=twenty-four) echo -n "area3[17] = " echo ${area3[17]} echo -n "area3[24] = " echo ${area3[24]} #----------------------------------------------- exit 0
به طوری که دیدهایم، یک روش مناسب ارزشگذاری یک آرایه کامل، استفاده از نماد array=( element1 element2 ... elementN ) است.
base64_charset=( {A..Z} {a..z} {0..9} + / = ) #با استفاده از بسط ابروی توسعهیافته، #+برای مقدار دهی اولیه عناصر آرایه. #استخراج شده از اسکریپت base64.sh در #+پیوست «اسکریپتهای اهدایی».
Bash عملیات آرایهای روی متغیرها را اجازه میدهد، حتی اگر متغیرها به طور صریح به عنوان آرایه تعریف نگردیده باشند. string=abcABC123ABCabc echo ${string[@]} # echo ${string[*]} # echo ${string[0]} # echo ${string[1]} #این یکبار دیگر ثابت میکند که متغیرهای Bash بدون نوع هستند. |
#!/bin/bash #چاپ شکیل یکی از اشعار محبوب نگارنده راهنمای ABS. #سطرهای شعر (بند منفرد). Line[1]="I do not know which to prefer," Line[2]="The beauty of inflections" Line[3]="Or the beauty of innuendoes," Line[4]="The blackbird whistling" Line[5]="Or just after." #توجه نمایید که نقلقول، گنجاندن فضاهای سفید را مجاز میکند. #ذکر منبع. Attrib[1]=" Wallace Stevens" Attrib[2]="\"Thirteen Ways of Looking at a Blackbird\"" #این شعر در مالکیت عمومی است (حق تالیف آن منقضی گردیده). echo tput bold # Bold print. for index in 1 2 3 4 5 #پنج سطر. do printf " %s\n" "${Line[index]}" done for index in 1 2 #دو سطر ذکر منبع. do printf " %s\n" "${Attrib[index]}" done tput sgr0 #تنظیم دوباره ترمینال، مستندات tput را ببینید. echo exit 0 #تمرین: #----------- #اسکریپت را برای چاپ کردن خوش فرم یک شعر از یک فایل داده متنی ویرایش کنید.
متغیرهای آرایهای دارای ترکیب دستوری خوشان هستند، حتی فرمانهای استاندارد Bash دارای گزینههای مخصوصِ وفق داده شده برای به کار بردن با آرایه هستند.
مثال 27-3. عملیات مختلف آرایه
#!/bin/bash #کارهای بیشتری با آرایهها. array=( zero one two three four five ) # echo ${array[0]} #zero echo ${array:0} #zero #بسط پارامتر اولین عضو، با شروع از محل شماره 0 (اولین کاراکتر). echo ${array:1} #ero #بسط پارامتر اولین عضو با شروع از محل شماره 1 (دومین کاراکتر). # مترجم: # echo ${array[3]:2} # ree # بسط پارامتر چهارمین عضو با شروع از محل شماره 2 (کاراکتر سوم) echo "--------------" echo ${#array[0]} #طول اولین عنصر آرایه. echo ${#array} #طول عضو اول آرایه (نماد جایگزین). echo ${#array[1]} #3 #طول عضو دوم آرایه. آرایهها در Bash از صفر شاخصگذاری میشوند. echo ${#array[*]} #تعداد عناصر آرایه. echo ${#array[@]} #تعداد عناصر آرایه. echo "--------------" array2=( [0]="first element" [1]="second element" [3]="fourth element" ) # #نقلقول، جای دادن فضای سفید در عضوهای منفرد آرایه را مجاز میکند. echo ${array2[0]} # echo ${array2[1]} # echo ${array2[2]} # #پرش در مقدار دهی اولیه، بنابراین تهی است. echo ${array2[3]} # echo ${#array2[0]} #(طول اولین عضو) echo ${#array2[*]} #(تعداد عناصر در آرایه) exit
بسیاری از عملیات رشتهای استاندارد، روی آرایهها عمل میکنند.
مثال 27-4. عملیات رشتهای روی آرایهها
#!/bin/bash #عملیات رشتهای روی آرایهها. #اسکریپت نوشته Michael Zick است. #با مجوز در این راهنما استفاده گردیده. #بهینهسازیها: 05 May 08، 04 Aug 08. #به طور کلی، هر عمل رشتهای با استفاده از نماد ${name ... } #+میتواند با نشانهگذاری ${name[@] ... } یا ${name[*] ...} #+روی تمام عناصر رشتهای در یک آرایه اِعمال گردد. arrayZ=( one two three four five five ) echo #استخراج رشته فرعی echo ${arrayZ[@]:0} # #تمام عناصر. echo ${arrayZ[@]:1} # #همه عناصر بعد از عضو [0]. echo ${arrayZ[@]:1:2} # #فقط دو عضو بعد از عضو [0]. #مترجم: توجه به دو نمونه زیر در فهم کاملتر چگونگی عملکرد موارد فوق موثر است. #echo ${arrayZ[2]:2} # ree استخراج از عنصر شماره 2 با شروع از محل شماره 2 #echo ${arrayZ[2]:2:2} # re از عنصر شماره 2، از محل شماره 2، تعداد 2 کاراکتر echo "---------" #پاک کردن رشته فرعی #حدف کوتاهترین انطباق از ابتدای رشته(ها). echo ${arrayZ[@]#f*r} # # #بر تمام عناصر آرایه اعمال میگردد. #با «four» منطبق میشود و آن را حذف میکند. #حذف بلندترین انطباق از ابتدای رشته(ها) echo ${arrayZ[@]##t*e} # # #بر تمام عناصر آرایه اثر میکند. #با «three» منطبق میشود و حذفش میکند. #حذف کوتاهترین انطباق از انتهای رشته(ها) echo ${arrayZ[@]%h*e} # # #بر تمام عناصر آرایه عمل میکند. #با «hree» مطابقت مینماید و حذفش میکند. #حذف بلندترین انطباق از انتهای رشته(ها) echo ${arrayZ[@]%%t*e} # # #بر تمام عناصر آرایه اعمال میشود. #با«three» تطبیق نموده و آن را حذف میکند. echo "----------------------" #تعویض رشته فرعی #تعویض اولین مورد تطابق رشته فرعی، با جانشین. echo ${arrayZ[@]/fiv/XYZ} # # #بر تمام عناصر عمل میکند. #تعویض تمام موارد تطابق رشته فرعی با جانشین. echo ${arrayZ[@]//iv/YY} # # #روی تمام عناصر آرایه عمل میکند. #حذف تمام موارد تطابق رشته فرعی. #مشخص نکردن رشته جانشین، حذف را پیشفرض میکند... echo ${arrayZ[@]//fi/} # #بر تمام عناصر آرایه اعمال میشود. #تعویض موارد انطباق جلویی رشته فرعی. echo ${arrayZ[@]/#fi/XY} # # #بر تمام عناصر آرایه عمل میکند. #تعویض موارد انطباق انتهایی رشته فرعی. echo ${arrayZ[@]/%ve/ZZ} # # #بر تمام عناصر آرایه عمل میکند. echo ${arrayZ[@]/%o/XX} # # #چرا؟ echo "------------------------------" replacement() { echo -n "!!!" } echo ${arrayZ[@]/%e/$(replacement)} # # #stdout تابع replacement() رشته جانشین است. #عمل تعویض، در حقیقت یک «تخصیص» است. echo "-------------------------------------" #دستیابی «for-each» (برای هر یک از عضوها): echo ${arrayZ[@]//*/$(replacement optional_arguments)} # # #اکنون، فقط در صورتیکه Bash رشته انطباق را #+به تابعی که فراخوانی میشود عبور بدهد . . . echo exit 0 #قبل از یک تلاش برجسته -- Perl، Python، یا بقیه موارد -- #به خاطر داشته باشید: #$( ... ) یک جایگزینی فرمان است. #یک تابع به عنوان یک پردازش فرعی اجرا میشود. #تابع خروجیاش را (اگر echo شده باشد) در stdout مینویسد. #تخصیص، در ترکیب با echo و جایگزینی فرمان میتواند از #+stdout تابع بخواند. #نماد name[@] مشخصکننده (معادل) یک عملیات «for-each» است. #Bash قدرتمندتر از آن است که شما فکر میکنید!
جایگزینی فرمان میتواند عناصر جداگانه یک آرایه را بسازد.
مثال 27-5. بار کردن محتویات یک اسکریپت به داخل یک آرایه
#!/bin/bash #اسکریپت به یک آرایه بارگذاری میکند. #بواسطه یک e-mail از Chris Martin (متشکرم!). script_contents=( $(cat "$0") ) #محتویات اسکریپت ($0) را #+در یک آرایه ذخیره میکند. for element in $(seq 0 $((${#script_contents[@]} - 1))) do #${#script_contents[@]} تعداد #+عناصر در آرایه را ارایه میدهد. # #پرسش: #چرا seq 0 لازم است؟ #تغییر آن به seq 1 را امتحان کنید. echo -n "${script_contents[$element]}" #لیست کردن هر فیلد این اسکریپت در یک سطر واحد. #echo -n "${script_contents[element]}" نیز به سبب ${ ... } کار میکند. echo -n " -- " #به کار بردن «--» به عنوان جداکننده فیلد. done echo exit 0 #تمرین: #--------- #اسکریپت را طوری ویرایش نمایید که خودش را در قالب اولیه، #+به طور کامل با فضای سفید، شکست سطرها، و غیره لیست کند.
در یک مضمون آرایهای، برخی فرمانهای داخلی Bash دارای مقصود کمی متفاوت هستند. برای مثال،unset عناصر آرایه یا حتی یک آرایه کامل را حذف میکند.
مثال 27-6. برخی خصوصیات ویژه آرایهها
#!/bin/bash declare -a colors #تمام فرمانهای بعدی در این اسکریپت با متغیر colors #+به عنوان یک آرایه رفتار میکنند. echo "Enter your favorite colors (separated from each other by a space)." read -a colors #جهت نمایش ویژگیهای زیر، حداقل ۳ رنگ وارد کنید. #گزینه خاص فرمان read برای مجاز نمودن تخصیص عناصر آرایه. echo element_count=${#colors[@]} #ترکیب دستوری ویژه جهت استخراج تعداد عناصر در آرایه. #ترکیب element_count=${#colors[*]} نیز کار میکند. # #متغیر «@» تفکیک کلمه داخل نقلقولها را میسر میکند #+(متغیرهای جدا شده به وسیله فضای سفید را استخراج میکند). # #این با رفتار «$@» و «$*» در پارامترهای مکانی مطابقت دارد. index=0 while [ "$index" -lt "$element_count" ] do #لیست کردن تمام عناصر آرایه. echo ${colors[$index]} #${colors[index]} نیز کار میکند، زیرا در درون براکتهای #${ ... } قرار دارد. let "index = $index + 1" #یا: # done #هر عضو آرایه در یک سطر جداگانه لیست میگردد. اگر این مطلوب #نیست، از echo -n "${colors[$index]} " استفاده کنید # #انجام این کار با یک حلقه for به صورت: # # # # #(با تشکر از S.C.) echo #دوباره، لیست تمام عناصر یک آرایه، اما با کاربرد یک روش برازندهتر. echo ${colors[@]} #echo ${colors[*]} نیز کار میکند. echo #فرمان unset عناصر یک آرایه یا تمام آرایه را حذف میکند. unset colors[1] #حذف دومین عنصر آرایه. #دارای همان اثر colors[1]= است echo ${colors[@]} #لیست دوباره آرایه، با غیبت دومین عضو. unset colors #حذف تمام آرایه. unset colors[*] و #+unset colors[@] نیز کار میکند. echo; echo -n "Colors gone." echo ${colors[@]} #یکبار دیگر لیست آرایه، اکنون تهی است. exit 0
همچنانکه در مثال قبل دیدهایم، هر یک از ترکیبهای ${array_name[@]} یا ${array_name[*]} به تمام عناصر آرایه ارجاع میدهند. به طور مشابهی، برای بدست آوردن تعداد عناصر در یک آرایه، یکی از نشانهگذاریهای ${#array_name[@]} یا ${#array_name[*]} را به کار ببرید. ${#array_name} طول (تعداد کاراکترهای) ${array_name[0]}، یعنی اولین عنصر آرایه است.
مثال 27-7. در باره آرایههای تهی و عناصر تهی
#!/bin/bash # #با تشکر از Stephane Chazelas برای مثال اولیه، و تشکر #+از Michael Zick و Omair Eshkenazi برای گسترش دادن آن. #وتشکر از Nathan Coulter برای توضیحات و اصلاحات. #یک آرایه تهی، با یک آرایه دارای عناصر تهی یکسان نیست. array0=( first second third ) array1=( '' ) #array1 شامل یک عضو تهی است. array2=( ) #بدون عضو، آرایه array2 تهی. array3=( ) #این آرایه چطور؟ echo ListArray() { echo echo "Elements in array0: ${array0[@]}" echo "Elements in array1: ${array1[@]}" echo "Elements in array2: ${array2[@]}" echo "Elements in array3: ${array3[@]}" echo echo "Length of first element in array0 = ${#array0}" echo "Length of first element in array1 = ${#array1}" echo "Length of first element in array2 = ${#array2}" echo "Length of first element in array3 = ${#array3}" echo echo "Number of elements in array0 = ${#array0[*]}" # echo "Number of elements in array1 = ${#array1[*]}" # echo "Number of elements in array2 = ${#array2[*]}" # echo "Number of elements in array3 = ${#array3[*]}" # } #=================================================================== ListArray #آزمون گسترش دادن آن آرایهها. #افزودن یک عضو به هر آرایه. array0=( "${array0[@]}" "new1" ) array1=( "${array1[@]}" "new1" ) array2=( "${array2[@]}" "new1" ) array3=( "${array3[@]}" "new1" ) ListArray #یا array0[${#array0[*]}]="new2" array1[${#array1[*]}]="new2" array2[${#array2[*]}]="new2" array3[${#array3[*]}]="new2" ListArray #وقتی به شکل فوق گسترش داده شود، آرایهها پشته هستند ... #موارد فوق «push» هستند (آخرین عنصر افزوده به پشته)... #بلندی پشته برابر است با: height=${#array2[@]} echo echo "Stack height for array2 = $height" #«pop» (یعنی واکشی بالاترین عنصر پشته) عبارت است از: unset array2[${#array2[@]}-1] #آرایهها بر مبنای 0 هستند، یعنی height=${#array2[@]} #+عضو اول دارای شاخص 0 است. #.مترجم: بنابراین شاخص آخرین عضو برابر با «تعداد عناصر منهای یک» میشود echo echo "POP" echo "New stack height for array2 = $height" ListArray #فقط عنصر دوم و سوم آرایه array0 لیست میشود. from=1 #شاخصگذاری از صفر شروع میشود. to=2 array3=( ${array0[@]:$from:$to} ) echo echo "Elements in array3: ${array3[@]}" #مانند یک رشته (آرایهای از کاراکترها) کار میکند. #امتحان برخی قالبهای رشتهای دیگر. #تعویض: array4=( ${array0[@]/second/2nd} ) echo echo "Elements in array4: ${array4[@]}" #تعویض تمام رشته منطبق شده با الگو. array5=( ${array0[@]//new?/old} ) echo echo "Elements in array5: ${array5[@]}" #درست وقتی خیال شما در این مورد آسوده میشود . . . array6=( ${array0[@]#*new} ) echo #این یکی ممکن است شما را متعجب نماید. echo "Elements in array6: ${array6[@]}" array7=( ${array0[@]#new1} ) echo #بعد از array6 این نباید یک غافلگیری باشد. echo "Elements in array7: ${array7[@]}" #که بسیار شباهت دارد به . . . array8=( ${array0[@]/new1/} ) echo echo "Elements in array8: ${array8[@]}" #بنابراین در این مورد چه میتوان گفت؟ #عملیات رشتهای به طور متوالی روی هر عنصر در var[@] انجام میگردد. #بنابراین : Bash عملیات برداری رشته را پشتیبانی میکند. #اگر نتیجه، رشتهای به طول صفر باشد، در تخصیص دادن نتیجه، آن عنصر #+ناپدید میگردد. #اما، اگر بسط در نقلقولها باشد، عناصر تهی باقی میمانند. #Michael Zick: پرسش، آیا آن رشتهها نقلقول ضعیف هستند یا نقلقول قوی؟ #Nathan Coulter: چیزی به عنوان «نقلقولهای ضعیف» وجود ندارد. #!در حقیقت آنچه روی میدهد آن است که انطباق الگو در مواردی از قبیل #!+${parameter#word} بعد از تمام بسط(کلمه)های دیگر صورت میگیرد. zap='new*' array9=( ${array0[@]/$zap/} ) echo echo "Number of elements in array9: ${#array9[@]}" array9=( "${array0[@]/$zap/}" ) echo "Elements in array9: ${array9[@]}" #این دفعه عناصرِ تهی باقی میمانند. echo "Number of elements in array9: ${#array9[@]}" #درست موقعی که فکر میکردید هنوز در کانزاس هستید . . . #array10=( ${array0[@]#$zap} ) echo echo "Elements in array10: ${array10[@]}" # مترجم: کنایه از «ذهنیت اشتباه داشتن» است. اما، اگر zap نقلقولی باشد، ستاره در آن تفسیر نخواهد شد. array10=( ${array0[@]#"$zap"} ) echo echo "Elements in array10: ${array10[@]}" #بسیار خوب، شاید باز هم ما در کانزاس هستیم . . . #(بازنگریهای بلوک کد فوق به وسیله Nathan Coulter) #آرایه array7 را با array10 مقایسه کنید. #آرایه array8 را با array9 مقایسه کنید. #تاکید دوباره: چیزی به عنوان نقلقول ضعیف نیست! #Nathan Coulter شرح میدهد: #انطباق الگوی «word» در ${parameter#word} بعد از #+بسط پارامتر و «قبل از» حدف نقلقول انجام میشود. #در حالت عادی، انطباق الگو «بعد از» حذف نقلقول #انجام میشود. exit
نسبت ${array_name[@]} و ${array_name[*]} قابل مقایسه با نسبت میان $@ و $* است. این نشانهگذاری قدرتمند آرایه، دارای چند مورد استفاده است.
#رونوشت برداری از یک آرایه. array2=( "${array1[@]}" ) #یا array2="${array1[@]}" # #اما این ترکیب به طوری که Jochen DeSmet اشاره میکند با آرایههای #+پراکنده، آرایههایی با حفره(عناصر غایب) در آنها، ناموفق است. #------------------------------------------------------------ array1[0]=0 #array1[1] تخصیص داده نشده array1[2]=2 array2=( "${array1[@]}" ) #آن را کپی میکند؟ echo ${array2[0]} #0 echo ${array2[2]} #(تهی)، ظاهرا باید 2 باشد #------------------------------------------------------------- #افزودن یک عنصر به یک آرایه. array=( "${array[@]}" "new element" ) #یا array[${#array[*]}]="new element" #با تشکر از S.C.
عملیات ارزشگذاری اولیه array=( element1 element2 ... elementN ) به کمک جایگزینی فرمان، بارگیری محتویات یک فایل متن به داخل یک آرایه را امکانپذیر میسازد. #!/bin/bash filename=sample_file # |
اسکریپتنویسی هوشمندانه، افزایش دادن عملیات آرایهای را امکانپذیر مینماید.
مثال 27-8. مقداردهی اولیه آرایهها
#! /bin/bash # #این عملیات آرایهای مختص Bash است، از اینرو #+پسوند .bash در نام اسکریپت به کار رفته است. # #مجوز: استفاده مجدد نامحدود، به هر طریق، برای هر مقصود. # # #شفاف سازی و توضیحات اضافی به وسیله William Park #بر اساس یک مثال ارایه شده توسط Stephane Chazelas #+که در یک نگارش قدیمی از این راهنما ظاهر گردید. #قالب خروجی فرمان times : #CPU سیستم <فاصله> CPU کاربر #CPU فرزندان مرده سیستم <فاصله> CPU فرزندان مرده کاربر #Bash دارای دو نگارش جهت تخصیص تمام عناصر یک آرایه #+به یک متغیر آرایهای جدید است. #در Bash نگارش 2.04 و بعد از آن، هر دوی آنها عناصر #+تهی را از قلم میاندازند. #شاید یک تخصیص آرایه اضافی که رابطه [subscript]=value #+برای آرایهها را حفظ کند، در نگارشهای بعدی اضافه شود. #با استفاده از یک فرمان داخلی یک آرایه بزرگ میسازد، #+اما هر چیز تولید کننده آرایهای با چند هزار عضو نیز #+مشکلی ایجاد نمیکند. declare -a bigOne=( /dev/* ) #تمام فایلهای داخل /dev echo echo 'Conditions: Unquoted, default IFS, All-Elements-Of' echo "Number of elements in array is ${#bigOne[@]}" #set -vx echo echo '- - testing: =( ${array[@]} ) - -' times declare -a bigTwo=( ${bigOne[@]} ) #به پرانتزها توجه کنید: times echo echo '- - testing: =${array[@]} - -' times declare -a bigThree=${bigOne[@]} #این دفعه بدون پرانتزها. times #مقایسه اعداد نشان میدهد که شکل دوم ارایه شده #+به وسیله Stephane Chazelas سریعتر است. # #به طوری که William Park شرح میدهد: #+آرایه bigTwo عضو به عضو تخصیص یافته است (به علت وجود پرانتزها)، #+در حالیکه آرایه bigThree به صورت یک رشته منفرد تخصیص یافته است. #بنابراین، در اصل، شما به این صورت دارید: # # # #این مطلب را با echo ${bigTwo[0]} و echo ${bigThree[0]} تحقیق کنید. #من توضیحات مثالم را با استفاده از شکل اول ادامه خواهم داد، به علت #+اینکه گمان دارم نمایش تجربی مناسبتری است از آنچه اتفاق میافتد. #بخشهای قابل استفاده مجدد مثالهای من شامل شکل دوم واقعی خواهند بود #+که این شکل به دلیل سرعت بالا مناسبتر است. #MSZ: دوستان از اشتباه نظری قبلی متاسفم. #یادداشت: #--------- #دستورالعملهای صریح «declare -a» در سطرهای 31 و 43 ضروری نیستند، #+چون به طور ضمنی در ترکیب تخصیص Array=( ... ) قرار دارند. #به هرحال، از قلم انداختن این اعلانها اجرای بخشهای بعدی اسکریپت #+را کند میکند. #امتحان کنید و ببینید. exit 0
اضافه کردن یک declare -a غیر ضروری برای یک اعلان آرایه، ممکن است اجرای عملیات بعدی روی آرایه را تسریع نماید. |
مثال 27-9. رونوشت برداری و الحاق آرایهها
#! /bin/bash # # #این اسکریپت به وسیله Michael Zick نوشته شده است. #با مجوز در اینجا استفاده گردیده است. #چگونگی «عبور دادن با نام و برگشت با نام» #+یا «ساختن عبارت فرمان تخصیص خودتان». CpArray_Mac() { #سازنده عبارت فرمان تخصیص echo -n 'eval ' echo -n "$2" #نام مقصد echo -n '=( ${' echo -n "$1" #نام منبع echo -n '[@]} )' #تمام آن میتوانست به صورت یک دستور منفرد باشد. #فقط مسئله سبک نگارش است. } declare -f CopyArray #نشانگر تابع CopyArray=CpArray_Mac #سازنده عبارت Hype() { #آرایهای به نام $1 را میگیرد. #(با آرایهای محتوی Really Rocks پیوند میزند.) #در آرایهای به نام $2 برگشت میدهد. local -a TMP local -a hype=( Really Rocks ) $($CopyArray $1 TMP) TMP=( ${TMP[@]} ${hype[@]} ) $($CopyArray TMP $2) } declare -a before=( Advanced Bash Scripting ) declare -a after echo "Array Before = ${before[@]}" Hype before after echo "Array After = ${after[@]}" #Too much hype? echo "What ${after[@]:3:2}?" declare -a modest=( ${after[@]:2:1} ${after[@]:3:2} ) #---- استخراج رشته فرعی ---- echo "Array Modest = ${modest[@]}" #چه اتفاقی برای before پیش آمده؟ echo "Array Before = ${before[@]}" exit 0
مثال 27-10. بیشتر در مورد الحاق آرایهها
#! /bin/bash # # #مجوز: استفاده مجدد نامحدود در هر شکل، به هر منظور. # # #اندکی به وسیله نگارنده ویرایش گردیده است. #عملیات آرایه مختص Bash است. #/bin/sh میراث یونیکس فاقد معادلهای آن است. #خروجی این اسکریپت را به فرمان more لولهکشی کنید #+به طوری که بتواند صفحه به صفحه مرور گردد، و یا #خروجی آن را به یک فایل تغییر مسیر بدهید. declare -a array1=( zero1 one1 two1 ) #عناصر مقدار دهی اولیه شدهاند. declare -a array2=( [0]=zero2 [2]=two2 [3]=three2 ) #مقدار دهی پراکنده -- [1] مشخص نگردیده. echo echo '- Confirm that the array is really subscript sparse. -' echo "Number of elements: 4" #به منظور روشنگری به صورت ثابت وارد گردیده است. for (( i = 0 ; i < 4 ; i++ )) do echo "Element [$i]: ${array2[$i]}" done #همچنین کد عمومیتر در مثال A-58 را ببینید. declare -a dest #ترکیب (پیوست) دو آرایه در آرایه سوم. echo echo 'Conditions: Unquoted, default IFS, All-Elements-Of operator' echo '- Undefined elements not present, subscripts not maintained. -' # #عناصر تعریف نشده، وجود ندارند، آنها از قلم افتادهاند. dest=( ${array1[@]} ${array2[@]} ) # #نتایج عجیب، یک باگ احتمالی. #اکنون، لیست کردن نتیجه. echo echo '- - Testing Array Append - -' cnt=${#dest[@]} echo "Number of elements: $cnt" for (( i = 0 ; i < cnt ; i++ )) do echo "Element [$i]: ${dest[$i]}" done #تخصیص یک آرایه به آرایه تک عضوی (دوبار). dest[0]=${array1[@]} dest[1]=${array2[@]} #لیست کردن نتیجه. echo echo '- - Testing modified array - -' cnt=${#dest[@]} echo "Number of elements: $cnt" for (( i = 0 ; i < cnt ; i++ )) do echo "Element [$i]: ${dest[$i]}" done #بازرسی عضو دوم ویرایش شده. echo echo '- - Reassign and list second element - -' declare -a subArray=${dest[1]} cnt=${#subArray[@]} echo "Number of elements: $cnt" for (( i = 0 ; i < cnt ; i++ )) do echo "Element [$i]: ${subArray[$i]}" done #تخصیص یک آرایه کامل به یک عضو منفرد از یک آرایه دیگر با استفاده از #+تخصیص آرایه =${ ... }، آرایهای را که باید تخصیص داده شود تبدیل به #+یک رشته متشکل از عناصر جدا شده با فاصله (کاراکتر اول IFS)نموده است. #اگر عناصر اولیه شامل فضای سفید نباشند . . . #اگر آرایه اولیه دارای ارزشگذاری پراکنده نباشد . . . #آنوقت ما میتوانیم دوباره ساختار آرایه اصلی را برگردانیم. #بازیابی عضو دوم ویرایش شده. echo echo '- - Listing restored element - -' declare -a subArray=( ${dest[1]} ) cnt=${#subArray[@]} echo "Number of elements: $cnt" for (( i = 0 ; i < cnt ; i++ )) do echo "Element [$i]: ${subArray[$i]}" done echo '- - Do not depend on this behavior. - -' echo '- - This behavior is subject to change - -' echo '- - in versions of Bash newer than version 2.05b - -' #MSZ: دوستان در باره هر نابسامانی قبلی متاسفم. exit 0
--
آرایهها گسترش دادن الگوریتمهای آشنای قدیمی به اسکریپتهای پوسته را میسر میکنند. تصمیمگیری در مورد آنکه آیا لزوما این ایده مناسبی است به خواننده واگذار میشود.
#!/bin/bash #مرتبسازی حبابی. #الگوریتم مرتبسازی حبابی را به یاد بیاورید. در این نگارش خاص... #با هر گذر متوالی آرایهای که باید مرتب بشود، دو عنصر همجوار #+مقایسه میشوند و اگر ترتیب آنها درست نباشد جابجا میگردند. #در انتهای اولین دور، درشتترین عنصر در انتها قرار میگیرد. #در انتهای دومین گذر، عنصر درشت بعدی در محل ماقبل آخر مینشیند. #و به همین ترتیب. #این به معنای آن است که در هر گذر متوالی جابجایی کمتری لازم است. #بنابراین شما متوجه افزایش سرعتی در چاپ دورهای بعدی خواهید شد. exchange() { #دو عنصر آرایه را جابجا میکند. local temp=${Countries[$1]} #ذخیره موقت برای جابجا کردن عنصر. Countries[$1]=${Countries[$2]} Countries[$2]=$temp return } declare -a Countries #تعریف آرایه در اینجا اختیاری است، چون در #+پایین مقدار دهی اولیه میشود. #دونیم کردن یک متغیر آرایه به چند سطر با به کار بردن یک کاراکتر #+کاراکتر گریز (\) مجاز است؟ #بله. Countries=(Netherlands Ukraine Zaire Turkey Russia Yemen Syria \ Brazil Argentina Nicaragua Japan Mexico Venezuela Greece England \ Israel Peru Canada Oman Denmark Wales France Kenya \ Xanadu Qatar Liechtenstein Hungary) # #+ clear #پاک کردن صفحه نمایش برای شروع کار. echo "0: ${Countries[*]}" #لیست آرایه کامل در گذر 0. number_of_elements=${#Countries[@]} let "comparisons = $number_of_elements - 1" count=1 #شماره گذر. while [ "$comparisons" -gt 0 ] #ابتدای حلقه بیرونی do index=0 #بازنشانی شاخص بعد از هر گذر برای ابتدای آرایه. while [ "$index" -lt "$comparisons" ] #ابتدای حلقه داخلی do if [ ${Countries[$index]} \> ${Countries[`expr $index + 1`]} ] #اگر خارج از ترتیب باشد... #یادآوری میشود که \> در داخل براکتهای منفرد عملگر مقایسه اسکی است. # #+نیز کار میکند. then exchange $index `expr $index + 1` #جابجایی. fi let "index += 1" #یا index+=1 در Bash نگارش 3.1 یا جدیدتر. done #انتهای حلقه داخلی #------------------------------------------------------------------------ #Paulo Marcel Coelho Aragao به عنوان گزینه سادهتر حلقه for را توصیه میکند. # # ## # # # # # # # #---------------------------------------------------------------------- let "comparisons -= 1" #چون درشتترین عنصر به انتها میرود، در #+هر گذر به یک مقایسه کمتر نیاز داریم. echo echo "$count: ${Countries[@]}" #چاپ آرایه حاصل شده، در انتهای هر گذر. echo let "count += 1" #افزایش شماره گذر. done #انتهای حلقه بیرونی #پایان کار. exit 0
--
آیا جای گرفتن آرایه در داخل آرایه امکانپذیر است؟
#!/bin/bash #آرایه تو در تو. #Michael Zick این مثال را فراهم نموده است. #+اصلاحات و توضیحات به وسیلهWilliam Park است. AnArray=( $(ls --inode --ignore-backups --almost-all \ --directory --full-time --color=none --time=status \ --sort=time -l ${PWD} ) ) #فرمانها و گزینهها. #فاصلهها با اهمیت هستند . . . و در بالا چیزی نقلقول نشده. SubArray=( ${AnArray[@]:11:1} ${AnArray[@]:6:5} ) #این آرایه دارای شش عضو است: #+ # # #آرایهها در Bash لیستهای پیوندی (دایرهای) از نوع رشته (char *) هستند. #بنابراین، در حقیقت این آرایه تودرتو نیست، اما از نظر وظیفه مشابه است. echo "Current directory and date of last status change:" echo "${SubArray[@]}" exit 0
--
آرایههای جاسازی شده در ترکیب با مرجعهای غیرمستقیم امکانات مجذوب کنندهای خلق میکنند
مثال 27-12. آرایههای جاسازی شده و مرجعهای غیر مستقیم
#!/bin/bash # #آرایههای جاسازی شده و مرجعهای غیر مستقیم. #اسکریپت توسط Dennis Leeuw. #استفاده شده با مجوز. #ویرایش شده توسط نگارنده. ARRAY1=( VAR1_1=value11 VAR1_2=value12 VAR1_3=value13 ) ARRAY2=( VARIABLE="test" STRING="VAR1=value1 VAR2=value2 VAR3=value3" ARRAY21=${ARRAY1[*]} ) #جاسازی ARRAY1 در درون این آرایه دوم. function print () { OLD_IFS="$IFS" IFS=$'\n' #برای چاپ هر عضو آرایه در یک سطر جداگانه. TEST1="ARRAY2[*]" local ${!TEST1} #ببینید اگر این سطر را حذف کنید چه اتفاقی رخ میدهد. #مرجع غیر مستقیم. #عناصر $TEST1 را برای این تابع قابل دسترس میسازد. #بیایید ببینیم تا اینجا چه چیزی فراهم کردهایم. echo echo "\$TEST1 = $TEST1" #فقط نام متغیر. echo; echo echo "{\$TEST1} = ${!TEST1}" #محتویات متغیر. #آنچه که یک مرجع غیرمستقیم انجام میدهد echo echo "-------------------------------------------"; echo echo #چاپ متغیر echo "Variable VARIABLE: $VARIABLE" #چاپ یک عنصر رشته IFS="$OLD_IFS" TEST2="STRING[*]" local ${!TEST2} #مرجع غیرمستقیم (همچون بالا). echo "String element VAR2: $VAR2 from STRING" #چاپ یک عضو آرایه TEST2="ARRAY21[*]" local ${!TEST2} #مرجع غیرمستقیم (همچون بالا). echo "Array element VAR1_1: $VAR1_1 from ARRAY21" } print echo exit 0 #به طوری که نویسنده اسکریپت یادداشت میکند، «میتوانید به #+آسانی آن را برای ایجاد named-hashها در bash بسط بدهید.» #تمرین (دشوار) برای خواننده: این کار را انجام دهید.
--
آرایهها امکان پیادهسازی نگارش اسکریپت پوسته برای غربال اراتوستن را فراهم میکنند. البته، یک برنامه کاربردی مصرفکننده منابع از این نوع بایستی در زبانهای ترجمهشونده از قبیل C نوشته بشود. به عنوان یک اسکریپت به طور مشقتباری آهسته اجرا میگردد.
#!/bin/bash # #غربال اراتوستن #الگوریتم باستانی برای پیدا کردن اعداد اول. #به نسبت بسیار زیادی، از برنامه معادل آن که در C نوشته شده #+باشد، آهستهتر اجرا میگردد. LOWER_LIMIT=1 #شروع کردن با 1 UPPER_LIMIT=1000 #تا 1000 #(اگر وقت اضافی دارید، میتوانید عدد بزرگتری انتخاب کنید.) PRIME=1 NON_PRIME=0 let SPLIT=UPPER_LIMIT/2 #بهینهسازی: #فقط نیازمند بررسی اعداد تا نیمه راه حد بالایی است. چرا؟ declare -a Primes #Primes[] یک آرایه است. initialize () { #مقدار دهی اولیه آرایه. i=$LOWER_LIMIT until [ "$i" -gt "$UPPER_LIMIT" ] do Primes[i]=$PRIME let "i += 1" done #تا اثبات بیگناهی، تمام عناصر آرایه مقصر (عدد اول) فرض میشوند. } sift () #غیر اولها را غربال میکند. { let i=$LOWER_LIMIT+1 #اجازه دهید با 2 شروع کنیم. until [ "$i" -gt "$UPPER_LIMIT" ]# مترجم: این تابع برای غربال کردن اعدادی که اول نیستند، از طریق یک حلقه while به حذف ضرایب عدد از میان مجموعه اعداد بین حد پایین و حد بالا اقدام میکند. چون هنگامی که از میانه راه حدبالایی عبور کند، # کوچکترین ضریب عدد (ضریب2) بزرگتر از حد بالایی خواهد شد، نیازی به ادامه کار نیست و بنابراین جهت # بهینهسازی میتوانیم در شرط حلقه untile به جای حد بالایی، مقدار نیمه راه یعنی $SPLIT را قرار بدهیم. # do if [ "${Primes[i]}" -eq "$PRIME" ] #غربال کردن اعدادی که قبلاً غربال شدهاند (برچسب غیر اول دارند)، لازم نیست. then t=$i while [ "$t" -le "$UPPER_LIMIT" ] do let "t += $i " Primes[t]=$NON_PRIME #برچسب زدن تمام مضربها به عنوان غیر اول. done fi let "i += 1" done } print_primes () { #اعضای آرایه Primes[] را که برچسب عدد اول دارند، چاپ میکند. i=$LOWER_LIMIT until [ "$i" -gt "$UPPER_LIMIT" ] do if [ "${Primes[i]}" -eq "$PRIME" ] then printf "%8d" $i #8 فاصله برای هر عدد، ستونهای تراز مطلوبی ارایه میکند. fi let "i += 1" done } #=========================================== # #فراخوانی ترتیبی توابع. initialize sift print_primes #این است آنچه برنامهنویسی ساختیافته مینامند. #=========================================== echo exit 0 # #کد پایین به علت وجود exit فوق، اجرا نخواهد شد. #این نگارش بهبود یافته غربال، نوشته Stephane Chazelas #+تا اندازهای سریعتر اجرا میشود. #باید با شناسه خط فرمان (عدد حد بالا) فراخوانی گردد. UPPER_LIMIT=$1 #دریافت از خط فرمان. let SPLIT=UPPER_LIMIT/2 #نیمه راه تا حداکثر. Primes=( '' $(seq $UPPER_LIMIT) ) i=1 until (( ( i += 1 ) > SPLIT )) #کنترل فقط تا نیمه راه. do if [[ -n ${Primes[i]} ]] then t=$i until (( ( t += i ) > UPPER_LIMIT )) do Primes[t]= done fi done echo ${Primes[*]} exit $?
مثال 27-14. غربال اراتوستن، بهینهسازی شده
#!/bin/bash #غربال اراتوستن بهینهسازی شده #اسکریپت نوشته Jared Martin با تغییرات بسیار کم به وسیله نگارنده. #در این راهنما با مجوز استفاده گردیده است (تشکر!). #بر اساس اسکریپت زیر از راهنمای پیشرفته اسکریپتنویسی. # #مرجع http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf #نتایج را با http://primes.utm.edu/lists/small/1000.txt کنترل کنید. #لازم است اما کافی نخواهد بود، به عنوان مثال ## مترجم: برای اجرای دستور فوق، این اسکریپت را در فایلی به نام sieve و جایی از PATH سیستم ذخیره نمایید. UPPER_LIMIT=${1:?"Need an upper limit of primes to search."} Primes=( '' $(seq ${UPPER_LIMIT}) ) typeset -i i t Primes[i=1]='' #1 عدد اول نیست. until (( ( i += 1 ) > (${UPPER_LIMIT}/i) )) #فقط تا iمین گذر لازم است. do #چرا؟ if ((${Primes[t=i*(i-1), i]})) #مبهم، اما آموزنده، استفاده از بسط حسابی در زیرنویس (شاخص). then until (( ( t += i ) > ${UPPER_LIMIT} )) do Primes[t]=; done fi done # echo #تعویض با اسکریپت اصلی برای چاپ شکیل (صفحه نمایش 80 ستونی). printf "%8d" ${Primes[*]} echo; echo exit $?
این تولید کنندههای عدد اول مبتنی بر آرایه را با نمونههای دیگری که از آرایه استفاده نمیکنند، مثال A-15، و مثال 16-46 مقایسه نمایید.
--
آرایهها تا اندازهای برای شبیهسازی ساختارهای دادهای که Bash دارای پشتبانی ذاتی برای آنها نیست، مناسب هستند.
مثال 27-15. شبیهسازی پشته پایین فشردنی
#!/bin/bash #شبیهسازی پشته پایین فشردنی #مشابه پشته CPU، یک پشته پایین فشردنی هم اقلام دادهها رابه طور ترتیبی ذخیره #+میکند، اما آنها را به ترتیب وارونه، آخرین ورودی اولین خروجی، بیرون میدهد. BP=100 #اشارهگر مبنای آرایه پشته. از 100 شروع میشود. SP=$BP #اشارهگر پشته. مقدار دهی آن با مبنای (پایین)پشته. Data= #محتویات جایگاه پشته. به دلیل محدودیت دامنه برگشت #تابع، باید از متغیر سراسری استفاده کند. # # # # # declare -a stack push() #قرار دادن در پشته. { if [ -z "$1" ] #چیزی برای push نیست؟ then return fi let "SP -= 1" #پایین بردن اشارهگر پشته. stack[$SP]=$1 return } pop() #بیرون کشیدن از پشته. { Data= #خالی کردن قلم داده. if [ "$SP" -eq "$BP" ] #پشته تهی است؟ then return fi #این همچنین مانع تجاوز SP از 100 میشود، #+یعنی از یک پشته فراری پیشگیری میکند. Data=${stack[$SP]} let "SP += 1" #بالا بردن اشارهگر پشته. return } status_report() #پی بردن به آنچه در حال وقوع است. { echo "-------------------------------------" echo "REPORT" echo "Stack Pointer = $SP" echo "Just popped \""$Data"\" off the stack." echo "-------------------------------------" echo } #================================================== #اکنون، برای سرگرمی. echo #ببینید اگر میتوانید چیزی از پشته خالی بیرون بکشید. pop status_report echo push garbage pop status_report #ورودی آشغال، خروجی آشغال. value1=23; push $value1 value2=skidoo; push $value2 value3=LAST; push $value3 pop #LAST status_report pop #skidoo status_report pop #23 status_report #آخرین ورودی، اولین خروجی! #توجه نمایید چگونه با هر push یکی از اشارهگر پشته #+کاسته میشود و با هر pop یکی به آن افزوده میشود. echo exit 0 #=================================================== #تمرینها: #---------- #(1 تابع "push()" را برای میسر نمودن push کردن چند عنصر بر #+روی پشته از طریق یک فراخوانی منفرد تابع، ویرایش کنید. #(2 تابع "pop()" را برای مجاز نمودن بیرون کشیدن چند عنصر #+از پشته با یک فراخوانی منفرد تابع، ویرایش نمایید. #(3 کنترل خطا برای عملیات حساس اضافه کنید، یعنی، برگشت #دادن یک کد خطا بر اساس موفقیت یا عدم موفقیت عملیات، #+و انجام عمل متناسب با آن. #(4 با استفاده از این اسکریپت به عنوان نقطه شروع یک ماشین #+حساب چهار عمل اصلی مبتنی بر پشته، بنویسید.
--
دستکاری ماهرانه «زیرنویسهای» آرایه ممکن است نیازمند متغیرهای واسطه باشد. برای پروژههای در برگیرنده این مورد، بار دیگر استفاده از یک زبان برنامهنویسی قدرتمند، از قبیل پرل یا C را در نظر بگیرید.
مثال 27-16. کاربرد آرایه پیچیده: واکاوی یک سری عجیب ریاضی
#!/bin/bash #Q-series شناخته شده Douglas Hofstadter: # # #این یک سری عدد صحیح «درهم و برهم» با رفتار #+عجیب و غیرقابل پیشبینی است. #بیست جمله نخست سری عبارتند از: # #کتاب _Goedel, Escher, Bach: An Eternal Golden Braid_ #+اثر Hofstadter صفحه 137 و بعد آن را ببینید. LIMIT=100 #تعداد جملهها برای محاسبه. LINEWIDTH=20 #تعداد جملههای چاپ شده در هر سطر. Q[1]=1 #دو جمله اول سری 1 هستند. Q[2]=1 echo echo "Q-series [$LIMIT terms]:" echo -n "${Q[1]} " #بیرون دادن دو جمله نخست. echo -n "${Q[2]} " for ((n=3; n <= $LIMIT; n++)) #عبارت حلقه به شیوه C do # #نیاز به شکستن عبارت به جملههای میانی است، چون Bash خیلی #+خوب آرایههای حسابی پیچیده را مدیریت نمیکند. let "n1 = $n - 1" # let "n2 = $n - 2" # t0=`expr $n - ${Q[n1]}` # t1=`expr $n - ${Q[n2]}` # T0=${Q[t0]} # T1=${Q[t1]} # Q[n]=`expr $T0 + $T1` # echo -n "${Q[n]} " if [ `expr $n % $LINEWIDTH` -eq 0 ] #قالببندی خروجی. then # echo #فاصله دادن بین سطرها برای مرتب شدن قطعهها. fi done echo exit 0 #این یک پیادهسازی تکرار کننده Q-series است. پیادهسازی #بازگشتی به عنوان تمرین واگذار میشود. #اخطار: محاسبه این سری به طور بازگشتی از طریق یک اسکریپت #+خیلی زیاد طول میکشد. C/C++ به مراتب سریعتر خواهد بود.
--
Bash فقط از آرایههای یک بعدی پشتیبانی میکند، اگر چه یک ترفند کوچک، شبیهسازی آرایه چند بعدی را میسر میسازد.
مثال 27-17. شبیهسازی یک آرایه دو بعدی، سپس کج کردن آن
#!/bin/bash #شبیهسازی یک آرایه دو بعدی. #یک آرایه یک بعدی از یک سطر واحد تشکیل میشود. #آرایه دوبعدی سطرهای متوالی را ذخیره میکند. Rows=5 Columns=5 #آرایه 5 X 5 declare -a alpha #اعلان char alpha [Rows] [Columns] #لازم نیست. چرا؟ load_alpha () { local rc=0 local index for i in A B C D E F G H I J K L M N O P Q R S T U V W X Y do #اگر میخواهید، از سایر علامتها استفاده کنید. local row=`expr $rc / $Columns` local column=`expr $rc % $Rows` let "index = $row * $Rows + $column" alpha[$index]=$i # let "rc += 1" done #ترکیب زیر سادهتر خواهد بود، اما به نحوی فاقد «طعم» آرایه دو بعدی است. #+ } print_alpha () { local row=0 local index echo while [ "$row" -lt "$Rows" ] #چاپ بر حسب شماره سطر: در حالیکه do #+سطر (حلقه بیرونی) ثابت میماند، #+ستون تغییر میکند. local column=0 echo -n " " #همتراز کردن آرایه مربع با آرایه لوزی. while [ "$column" -lt "$Columns" ] do let "index = $row * $Rows + $column" echo -n "${alpha[index]} " # let "column += 1" done let "row += 1" echo done #معادل سادهتر آن عبارت است از # echo } filter () #فیلتر کردن شاخصهای منفی آرایه. { echo -n " " #کج شدن را تامین میکند. #چگونگی را شرح بدهید. if [[ "$1" -ge 0 && "$1" -lt "$Rows" && "$2" -ge 0 && "$2" -lt "$Columns" ]] then let "index = $1 * $Rows + $2" #اکنون چاپ آن به صورت مایل. echo -n " ${alpha[index]}" # fi } rotate () #45 درجه دوران آرایه -- { #+تراز آن روی گوشه سمت چپ پایینش. local row local column for (( row = Rows; row > -Rows; row-- )) do #پیمایش آرایه به طور وارونه. چرا؟ for (( column = 0; column < Columns; column++ )) do if [ "$row" -ge 0 ] then let "t1 = $column - $row" let "t2 = $column" else let "t1 = $column" let "t2 = $column + $row" fi filter $t1 $t2 #فیلتر کردن شاخصهای منفی آرایه. #اگر این کار را انجام ندهید چه میشود؟ done echo; echo done #چرخش آرایه از مثال (صفحات 143-146) در «برنامهنویسی پیشرفته #+C روی IBM PC» نوشته Herbert Mayer الهام گرفته شده است. #+(قسمت کتابنامه را ببینید.) #این درست نشان میدهد که بیشتر آنچه در C میتواند انجام شود، #+در اسکریپتنویسی پوسته نیز میتواند انجام بشود. } #-------------- اکنون، بیاید نمایش را شروع کنیم. ----------- load_alpha #بار گرفتن آرایه. print_alpha #چاپ کردن آن. rotate #چرخش 45 درجهای آن در خلاف جهت عقربههای ساعت. # exit 0 #این بیشتر یک طرح است، به ظاهر نازیبای آن توجه نکنید. #تمرینها: #----------------------- #(1 توابع بارگیری و جاپ آرایه را با یک شیوه بیشتر قابل درک #و کمتر نامفهوم، بازنویسی نمایید. # #(2 معین کنید توابع دوران دادن آرایه چگونه عمل میکنند. #اشاره: به معنای تلویحی شاخصگذاری وارونه آرایه فکر کنید. # #(3 این اسکریپت را برای کار کردن با یک آرایه غیر چهار گوش #به عنوان مثال یک آرایه 6 X 4 بازنویسی کنید. #موقع چرخاندن آرایه سعی کنید بدریختی آن را کمینه نمایید.
یک آرایه دو بعدی در اصل مانند یک آرایه یک بعدی، اما با شیوههای آدرسدهی اضافی برای مراجعه و دستکاری عناصر انفرادی به وسیله موقعیت سطر و ستون است.
برای یک مثال با جزییات بیشتر هم، مثال A-10 را ببینید.
--
برای اسکریپتهای جالبتر استفاده از آرایهها، مثالهای زیر را ببینید: