چند روش موجود است که میتوانید آرایهها را ایجاد نموده یا با دادهها پر کنید. یک روش صحیح منفرد وجود ندارد: روشی که شما نیاز خواهید داشت بستگی به آن دارد که دادهها کدامند و از کجا میآیند.
سادهترین راه برای ایجاد یک آرایه ساده با داده، استفاده از ترکیب
$names =( "Bob" "Peter" "$USER" "Big Bad John" )
این ترکیب دستوری(syntax) برای ایجاد آرایههایی با دادههای ایستا یا مجموعهای از پارامترهای رشتهای معلوم، عالی است، اما قابلیت انعطاف بسیار کمی برای افزودن مقادیر زیاد عناصر آرایه، در اختیار میگذارد. اگر انعطاف پذیری بیشتری میخواهید، میتوانید از شاخصهای صریح استفاده کنید:
$names =( # or... $[0] ="Bob"[1] ="Peter"[20] ="$USER"[21] ="Big Bad John")names [0] = "Bob"
توجه نمایید که بین شاخص 1و 20 در این مثال یک شکاف وجود دارد. یک آرایه باحفرههایی در آن آرایه پراکنده نامیده میشود. Bash این امر را اجازه میدهد واغلب میتواند کاملاً سودمند باشد.
اگر میخواهید یک آرایه را با نام فایلها پر کنید، ممکن است احتمالاً بخواهید از Globs استفاده کنید:
$photos =(~/"My Photos"/*.jpg)
توجه نمایید که در اینجا بخش
متأسفانه، به راستی ایجاد آرایههای ابهام آمیز با یک گروه نام فایل که به روش زیر ایجاد میشوند، آسان است:
$files =$(ls) # BAD, BAD, BAD! $files =($(ls)) # STILL BAD!
به یاد داشته باشید همیشه از کاربرد ls به این شکل پرهیز کنید، اولی یک رشته با خروجی فرمان ls ایجاد میکند. آن رشته احتمالاً به دلیلی که در مقدمه
روش صحیح انجام آن این است:
$files =(*) # Good!
این جمله یک آرایه به ما میدهد که در آن هر نام فایل یک عنصر جداگانه است. کامل!
این بخش که در اینجا مطرح میکنیم شامل برخی مفاهیم پیشرفته است. اگر هنوز آماده نیستید، شاید بخواهید پس از اینکه تمام این راهنما را خواندید به اینجا بازگردید. اگر میخواهید با موارد ساده ادامه دهید، میتوانید بااستفاده از آرایهها به پیش بروید.
گاهی اوقات میخواهیم یک آرایه از یک رشته یا خروجی یک فرمان تشکیل بدهیم. خروجی فرمانها رشته هستند: برای نمونه، اجرای یک فرمان find نام فایلها را به شمار میآورد و آنها را با یک کاراکتر سطر جدید(قرار دادن هر نام فایل در یک سطر جداگانه) از هم جدا میکند. بنابراین برای تفکیک یک رشته بزرگ به داخل یک آرایه، لازم است به Bash بگوییم هر عضو کجا به انتها میرسد. (تذکر، این یک مثال بد است، چون نام فایل میتواند شامل یک سطر جدید باشد،بنابراین جدا کردن آنها با سطر جدید نمیتواند ایمن باشد! اما مثال زیر را نگاه کنید.)
آنچه برای شکستن یک رشته به کار میرود محتوای متغیر
$IFS = . read-a ip_elements <<< "127.0.0.1"
در اینجا از متغیر
(دستور داخلی read و عملگر
میتوانستیم همین کار را با دستور find انجام بدهیم، در صورتیکه متغیر
بنابراین، آیا روشی برای دریافت لیستی از عناصر از یک برنامه خارجی ( مانند find) در یک آرایه Bash وجود دارد؟ به طور کلی، پاسخ بلی است، به شرط آنکه راه قابل اطمینانی برای جداسازی عناصر موجود باشد.
در یک حالت خاص از نام فایلها، پاسخ این مشکل، بایتهای تهی(NUL) است. یک بایت تهی، بایتی است که همه بیتهای آن صفر است: 00000000. رشتههای Bash نمیتوانند شامل بایتهای تهی باشند، به عنوان یک محصول زبان برنامهنویسی "C" : در زبان C بایت تهی برای علامت گذاری انتهای رشته به کاررفته است. از این جهت Bash که به زبان C نوشته شده و از رشتههای بومی C استفاده میکند، این رفتار را به ارث میبرد.
یک جریان داده( مانند خروجی یک فرمان، یا یک فایل ) میتواند شامل بایت تهی باشد. جریانها مانند رشتهها هستند، با سه تفاوت عمده: آنها به صورت ترتیبی خوانده میشوند(به طور معمول نمیتوانید با پرش از روی آنها عبور کنید)، آنها یک سویه میباشند( شما میتوانید از آنها بخوانید یا در آنها بنویسید، اما به طور نوعی هر دو با هم میسر نیست )، و آنها میتوانند شامل بایتهای تهی باشند.
نه نامهای فایل میتوانند شامل بایت تهی باشند( چون آنها توسط یونیکس همانند رشتههای C تکمیل شدهاند )، و نه اکثریت وسیع اقلام قابل خواندن برای انسان که شاید ما بخواهیم در یک اسکریپت ذخیره کنیم(ازقبیل نام افراد، آدرسهای IP، و غیره ). این موضوع NUL را یک نامزد عالی برای جداسازی عناصر در یک جریان ، میسازد. به طور کلی اغلب، دستوری که میخواهید خروجی آن را بخوانید، یک گزینهای خواهد داشت، که خروجیاش را به صورت جدا شده با بایت تهی، به جای سطر جدید یا کاراکتر دیگری، ایجاد میکند.
files =() while read-r -d $'\0'; do files +=("$ REPLY ")done < <( find/ foo -print0 )
این یک روش مطمئن تفکیک خروجی یک فرمان به رشتهها میباشد. به طور قابل فهمی، ابتدا کمی به هم پیچیده و گیج کننده به نظر میرسد. لذا، بیایید کمی آن را باز کنیم:
سطر اول
ما از یک حلقه while استفاده میکنیم که هر مرتبه یک دستور read را اجرا میکند. فرمان read از گزینه
وقتی read مقداری از داده ها را میخواند و با یک بایت تهی مواجه میشود، بدنه حلقه
برای انجام این کار، ما از ترکیب
و سرانجام، ترکیب دستوری
همان طور که قبلاً بیان گردید، فرمان find خود با یک گزینه
آرایهها یک لیست مطمئن از رشتهها هستند. آنها برای نگهداری چندین نام فایل، بدون عیب میباشند.
اگر شما باید یک جریان داده را به اجزاء تشکیل دهنده عناصر تفکیک نمایید، باید طریقهای برای گفتن آنکه هر عنصر از کجا شروع و به کجا ختم میگردد، وجود داشته باشد. بسیاری اوقات، بایت تهی بهترین انتخاب برای این کار میباشد.
اگر لیستی از اقلام دارید، تا آنجا که ممکن است آن را به صورت یک لیست حفظ کنید. تا موقعی که واقعاً لازم نیست، آن را در یک رشته یا فایل تخریب نکنید. اگر باید به تفصیل آن را در یک فایل بنویسید و بعداً آنرا بخوانید، مشکل جداکننده را که در بالاتوضیح داده شد، به خاطر داشته باشید.
در مستندات گنو: Arrays
در پرسش و پاسخهای رایج:
چگونه میتوانم از متغیرهای آرایهای استفاده کنم؟
چطور میتوانم از متغیرهای متغیر( متغیرهای غیرمستقیم، اشارهگرها، مرجعها ) یا آرایههای انجمنی استفاده کنم؟
چگونه میتوانم نام فایلهای شامل کاراکتر سطرجدید، فاصله، یا هردو را پیدا کرده و با آنها کار کنم؟
من متغیرهایی را در یک حلقه مقرر میکنم. چرا آنها پس از اتمام حلقه، ناگهان ناپدید میگردند؟ یا، چرا نمیتوانم دادهها را برای خواندن لولهکشی نمایم؟