منبع اصلی نوشتار زیر در این لینک قرار دارد

استفاده از آرایه‌ها

ادامه یادداشت قبل


راهنمای آموزشی  BashGuide   مؤلف  Lhunath

استفاده از آرایه‌ها

استفاده از مزیت عناصر آرایه‌ها به راستی آسان است. به علت آنکه یک آرایه وسیله مطمئن ذخیره است، ما به سادگی می‌توانیم یک حلقه for را برای تکرار روی عناصر آن، به کار ببریم:

 $ for file in \"$>{myfiles[@]}\"; do
 >     cp \"$file\" /backups/
 > done

به ترکیب دستوری استفاده شده برای بسط آرایه در اینجا توجه نمایید. ما شکل نقل‌قولی به کار برده‌ایم: ‎ \"${myfiles[@]}\"‎. سپس Bash این ترکیب را با هر عنصر منفرد در آرایه، تعویض می‌نماید، نقل‌قولی صحیح.

دو مثال زیر نتیجه یکسان دارند:

 $ names=(\"Bob\" \"Peter\" \"$USER\" \"Big Bad John\")
 $ for name in \"${names[@]}\"; do echo \"$name\"; done

 $ for name in \"Bob\" \"Peter\" \"$USER\" \"Big Bad John\"; do echo \"$name\"; done

مثال اول یک آرایه به نام names ایجاد می‌کند، که با چند عضو پر شده است. سپس آرایه به این عناصر بسط می‌یابد، که بعد توسط حلقه for به کار می‌روند. در مثال دوم، از آرایه صرف نظر کرده‌ایم و لیست اقلام را به طور مستقیم به حلقه for داده‌ایم.

به خاطر داشته باشید، بسط ‎ ${arrayname[@]}‎ را به طور صحیح نقل‌قولی نمایید. در غیر اینصورت، تمام مزایای استفاده از آرایه را از دست می‌دهید: رها کردن شناسه‌های غیر نقل‌قولی، به معنی آنست که به Bash برای تفکیک آنها به قطعات و جداسازی دوباره آنها تأییدیه می‌دهید.

مثال فوق آرایه را در یک ساختار حلقه for بسط می‌دهد. اما می‌توانید آرایه را در هرجایی که بخواهیدعناصر آن را به عنوان شناسه قرار دهید، بسط بدهید، در یک فرمان cp :

 myfiles=(db.sql home.tbz2 etc.tbz2)
 cp \"${myfiles[@]}\" /backups/

این مثال، دستور cp را، با تعویض عبارت ‎ \"${myfiles[@]}\"‎ با همه نام فایل‌های موجود در آرایه myfiles اجرا می‌نماید، نقل‌قول شده صحیح. پس از انجام بسط، Bash به طور مؤثر دستور زیر را اجرا می‌کند:

 cp \"db.sql\" \"home.tbz2\" \"etc.tbz2\" /backups/

فرمان cp فایلها را به دایرکتوری /backups/ شما کپی خواهد نمود.

همچنین می‌توانیدعناصر منفرد آرایه را با ارجاع به شماره عضویت آنها(که index یا شاخص نام دارد)، بسط بدهید. به خاطر داشته باشید، که به طور پیش‌فرض،آرایه‌ها zero-based می‌باشند، یعنی شماره شاخص اولین عضو آنها صفر می‌باشد:

 $ echo \"The first name is: ${names[0]}\"
 $ echo \"The second name is: ${names[1]}\"

( می‌توانید آرایه‌ای بدون عضو شماره صفر ایجاد کنید. آنچه قبلاً در مورد آرایه‌های پراکنده گفتیم را به خاطر بیاورید --شما می‌توانید بین شاخص‌ها حفره داشته باشید--، و این مطلب در ابتدای آرایه نیز به همان خوبی صدق می‌کند. این وظیفه شما به عنوان برنامه‌نویس است که بدانیدکدام‌یک از آرایه‌های شما به طور بالقوه پراکنده است، و کدام‌یک اینطور نیست.)

روش دیگری نیز برای بسط تمام عناصر آرایه وجود دارد، که به شکل ‎ \"${arrayname[*]}\"‎ می‌باشد. این شکل فقط برای تبدیل آرایه به یک رشته منفردکه تمام عناصر آرایه در آن باهم متصل گردیده‌اند، مفید می‌باشد. مقصود اصلی در این روش ارائه خروجی آرایه به اشخاص می‌باشد:

 $ names=(\"Bob\" \"Peter\" \"$USER\" \"Big Bad John\")
 $ echo \"Today\'s contestants are: ${names[*]}\"
 Today\'s contestants are: Bob Peter lhunath Big Bad John

توجه نمایید که در رشته حاصل شده، راهی برای گفتن آنکه نامها، کجا شروع و کجا ختم گردیده‌اند، وجود ندارد! این است چرایی آنکه، هر چیزی را تا آنجا که ممکن است، جدا نگاه می‌داریم.

به خاطر داشته باشید، هنوز هم به دقت نقل‌قولی نمایید! اگر ‎ ${arrayname[*]}‎ را نقل‌قولی نکنید، یکبار دیگر تفکیک کلمه Bash موجب بریدن آن به تکه‌ها می‌گردد.

می‌توانید متغیر IFS را با ‎ ${arrayname[*]}‎ ترکیب کنید، که نشان بدهید از چه کاراکتری برای جدا کردن عناصر آرایه از یکدیگر، موقعی که آنها را در یک رشته منفرد ادغام می‌کنید، استفاده شود. برای مثال، وقتی می‌خواهید نامها با کاراکتر کاما از هم جدا شوند، به راحتی به صورت زیر انجام می‌گردد:

 $ names=(\"Bob\" \"Peter\" \"$USER\" \"Big Bad John\")
 $ ( IFS=,; echo \"Today\'s contestants are: ${names[*]}\" )
 Today\'s contestants are: Bob,Peter,lhunath,Big Bad John

توجه نمایید که در این مثال، چگونه جمله‎ IFS=,; echo ...‎ را با قرار دادن بین ( و ) در یک Subshell یا پوسته فرعی اجرا نمودیم. چنین کردیم زیرا نمی‌خواهیم مقدار پیش‌فرض متغیر IFS در پوسته اصلی را تغییر بدهیم. موقعی که پوسته فرعی خارج می‌شود، متغیر IFS بازهم مقدار پیش‌فرض را دارد، و دیگر کاما نمی‌باشد. این اهمیت دارد، به دلیل آنکه متغیر IFS برای موارد بسیاری استفاده می‌شود، و تغییر مقدار آن به چیزی غیر از مقدار پیش‌فرض، رفتار غریبی را که انتظار آن را ندارید، موجب خواهد شد!

افسوس، بسط \"${array[*]}\" فقط کاراکتر اول از متغیر IFS را برای بهم پیوستن عناصر با یکدیگر به کار می‌گیرد. اگر در مثال قبل، می‌خواستیم نامها را با یک کاما و یک فاصله از یکدیگر جدا کنیم، می‌باید برخی تکنیک‌های دیگر را به کار می‌بردیم( به عنوان مثال، یک حلقه for ).

فرمان printf در اینجا سزاوار یک یادآوری می‌باشد، زیرا روش فوق العاده برازنده نسخه برداری از یک آرایه است:

 $ names=(\"Bob\" \"Peter\" \"$USER\" \"Big Bad John\")
 $ printf \"%s\\n\" \"${names[@]}\"
 Bob
 Peter
 lhunath
 Big Bad John

البته یک حلقه for نهایت انعطاف‌پذیری را ارائه می‌نماید، اما printf و حلقه ضمنی آن روی شناسه‌ها، می‌تواند بسیاری موارد ساده‌تر را پوشش بدهد. حتی می‌تواند جریانهای جدا شده با بایت تهی را، برای بازیابی بدون نقص بعدی تولید کند:

 $ printf \"%s\\0\" \"${myarray[@]}\" > myfile

یک نکته پایانی: شما می‌توانید تعداد عناصر یک آرایه را با استفاده از ‎ ${#array[@]}‎ به دست آورید.

 $ array=(a b c)
 $ echo ${#array[@]}
 3


  • تکرار مفید:
    همیشه بسط آرایه‌ها را به طور صحیح نقل‌قولی کنید، درست همانطور که بسط پارامترهای معمولی را نقل‌قولی می‌کنید .
    از ‎ ${#myarray[@]}‎ برای بسط تمام عناصر آرایه استفاده کنید و ‎ ${#myarray[*]}‎ را فقط موقعی که می‌خواهید همه عناصر آرایه را در یک رشته منفرد با یکدیگر متصل کنید، به کار ببرید.


ادامه دارد ....