آموزش‌های خط فرمانی

این وبلاگ تلاش می‌کند گامی در حد بضاعت در جهت آموزش خط فرمان و اسکریپت‌نویسی پوسته گنو-لینوکس بردارد.

آموزش‌های خط فرمانی

این وبلاگ تلاش می‌کند گامی در حد بضاعت در جهت آموزش خط فرمان و اسکریپت‌نویسی پوسته گنو-لینوکس بردارد.

توصیف‌گرهای فایل

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


3. توصیف‌گرهای فایل

توصیف‌گرهای فایل (به طور کوتاه: FDها) روشی برای ارجاع برنامه‌ها به فایلها، یا منابع دیگری که همانند فایلها کارمی‌کنند( از قبیل لوله‌ها،دستگاهها، سوکت‌ها، یا ترمینال‌ها ) می‌باشند. FDها نوع مشابه اشاره‌گرها به منابع داده، یا محل‌هایی که اطلاعات می‌توانند نوشته شوند، هستند. موقعی که چیزی از آن FD, خوانده یا در آن نوشته می‌شود، داده در حال نوشته شدن در منبع FD یا خوانده شدن از آن می‌باشد.

به طور پیش‌فرض، هر فرایند جدیدی با سه FD آغاز می‌شود. به این توصیف‌گرهای فایل با نام‌های ورودی استاندارد، خروجی استاندارد و خطای استاندارد رجوع می‌شود.در حالت کوتاه شده به ترتیب stdin و stdout و stderr نامیده می‌شوند. در یک پوسته محاوره‌ای، یا اسکریپت درحال اجرا در ترمینال، ورودی استاندارد طریقی است که bash کاراکترهای تایپ شده توسط شما در صفحه کلیدتان را می‌بیند. خروجی استاندارد جایی است که برنامه اکثر اطلاعات معمولی‌اش را به طوری که کاربر بتواند آن را ببیند، ارسال می‌کند، و خطای استاندارد جایی است که برنامه پیغام‌های خطایش را می‌فرستد. آگاه باشید که برنامه‌های کاربردی رابط گرافیگی هنوز به همین روش عمل می‌کنند، اما رابط گرافیگی واقعی کاربر از طریق این FDها کار نمی‌کند.برنامه‌های رابط گرافیکی هنوز می‌توانند از FDهای استاندارد بخوانند یا در آنها بنویسند، اما به طور معمول چنین نمی‌کنند. معمولاً، آنها تمام ارتباط متقابل با کاربر را از راه آن GUI انجام می‌دهند، که کنترل آن برای BASH را دشوار می‌سازد. در نتیجه، ما در برنامه‌های کاربردی ساده ترمینال خواهیم ماند. برنامه‌هایی، که به آسانی داده‌ها را به ورودی استانداردشان بخورانیم، و داده‌ها را از خروجی استاندارد و خطای استانداردشان بخوانیم.

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

    $ read -p "What is your name? " name; echo "Good day, $name.  Would you like some tea?"
    What is your name? lhunath
    Good day, lhunath.  Would you like some tea?

read دستوری است که اطلاعات را از stdin می‌خواند و در یک متغیر ذخیره می‌کند. ما تعیین نموده‌ایم که name آن متغیر باشد. وقتی read یک سطر اطلاعات را از stdin بخواند، خاتمه یافته و echo اجازه می‌یابد یک پیغام نمایش دهد. echo از stdout برای ارسال خروجی‌اش استفاده می‌کند. stdin به دستگاه ورودی پایانه شما که احتمالاً صفحه کلید شما می‌باشد، متصل گردیده است. stdout به دستگاه خروجی پایانه شما متصل گردیده است، که ما فرض می‌کنیم نمایشگر کامپیوتر شما است. در نتیجه، شما می‌توانید نام خود را تایپ نموده و با یک پیغام خوش‌آمد گویی دوستانه در نمایشگر خود به یک فنجان چای دعوت شوید.

پس stderr چیست؟ اجازه دهید نمایش بدهیم:

    $ rm secrets
    rm: cannot remove `secrets': No such file or directory

بدون داشتن فایلی به نام secrets در دایرکتوری جاری خودتان، آن دستور rm با شکست مواجه خواهد شد و یک پیغام خطا در تشریح آنچه اشتباه است، نمایش می‌دهد. چنین پیغام خطاهایی بر حسب قرارداد در stderr نمایش داده می‌شوند. stderr نیز به دستگاه خروجی پایانه شما متصل گردیده است، درست مانند stdout. در نتیجه، پیغام‌های خطا در نمایشگر شما نشان داده می‌شوند درست مانند پیغام‌ها در stdout. به هرحال، این افتراق، جدانگاه داشتن خطاها از پیغام‌های معمول برنامه‌ها را تسهیل می‌کند. بعضی افراد مایل هستند تمام خروجی در stderr را به رنگ قرمز بسته‌بندی کنند، به طوری که بتوانند پیغام‌های خطا را واضح‌تر ببیند. این به طور کلی قابل توصیه نیست، اما یک مثال ساده ازامکانات بسیاری است که این جدایی برای ما فراهم می‌کند. تکنیک رایج دیگر، نوشتن stderr در یک فایل ثبت وقایع(log file) خاص است.


  • تکرار مفید:
    به خاطر داشته باشید موقعی که اسکریپت‌ها را ایجاد می‌کنید،شما باید پیغام خطاهای سفارشی خود را به توصیف‌گر stderr ارسال نمایید. این یک قرارداد است و پیروی برنامه‌های کاربردی از قرارداد بسیار مناسب است. به همین ترتیب, به طوری‌که به زودی در باره تغییر مسیر خواهید آموخت، اما اجازه دهید من به سرعت اشاره‌ای به آن داشته باشم:

        echo "Uh oh.  Something went really bad.." >&2


  • توصیف‌گر فایل: یک شاخص عددی ارجاع به یکی از فرآیندهای فایل باز است. هر دستوری حداقل سه توصیف‌گر اصلی دارد: FD شماره 0، stdin است، FD شماره 1، stdout است و FD شماره 2، stderr می‌باشد.


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

محیط

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


2. محیط

هر برنامه‌ای اطلاعات، منابع، امتیازها و محدودیت‌هایی از پردازش والد خود به ارث می‌برد. ( برای بحث پیشرفته‌تر در این موضوع، بخش مدیریت پردازش‌ را ملاحظه کنید.)یکی از آن منابع، مجموعه‌ای از متغیرها به نام متغیرهای محیط می‌باشند.

در Bash, متغیرهای محیط تا اندازه بسیار زیادی مشابه متغیرهای معمولی مورد استفاده ما، کار می‌کنند. تنها تفاوت واقعی، آن است که آنها قبلاً، موقعی که اسکریپت شروع به اجرا می‌کند، مقرر شده‌اند، ما خودمان نباید به آنها مقداردهی کنیم.

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

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

متغیرهای محیط همچنین می‌توانند به طور بینهایت آسانی در حین کار تنظیم گردند( آسان‌تر از آنکه اگر همان اطلاعات در یک فایل ذخیره شده باشند). موقعی که در Bash دستوری را اجرا می‌کنید، گزینه‌ای دارید، برای تعیین یک تغییر موقتی محیط که فقط در طول مدت اجرای آن فرمان مؤثر است. این با قرار دادن عبارت VAR=value جلوی آن فرمان انجام می‌شود. در اینجا یک مثال آورده‌ایم:

    $ ls /tpm
    ls: no se puede acceder a /tpm: No existe el fichero o el directorio
    $ LANG=C ls /tpm
    ls: cannot access /tpm: No such file or directory

محیط موقتی LANG=C باعث نمی‌شود که منطقه کاربر برای مورد دیگری غیر از آن فرمانی که بعد از آن تایپ گردیده است، تغیر نماید.

اگر می‌دانید که برخی اطلاعات در یک متغیر محیط ذخیره شده است، در اسکریپت، می‌توانید درست مانند سایر متغیرها از آن استفاده کنید:

    if [[ $DISPLAY ]]; then
        xterm -e top
    else
        top
    fi

این مثال، در صورتی که متغیر محیطی DISPLAY تنظیم شده باشد( و تهی نباشد )دستور ‎ xterm -e top را اجرا می‌کند، در غیر آن صورت، دستور top را اجرامی‌نماید.

اگر می‌خواهید اطلاعاتی را در متغیر محیطی قرار دهید که به پردازش‌های فرزند به ارث برسد، فرمان export را به کار ببرید:

    export MYVAR=something

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

تغییر محیط و سپس اجرا، برای برخی برنامه‌ها به شدت رایج می‌باشد. اسکریپتی که این کار را به عنوان وظیفه اصلی‌اش انجام می‌دهد یک WrapperScript می‌نامند.


  • تکرار مفید:
    در اسکریپت‌های خود از نامهای تماماً با حروف بزرگ برای متغیرها استفاده نکنید. برای پرهیز از تصادمات، حروف کوچک یا ترکیبی از کوچک و بزرگ به کار ببرید .



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

ورودی و خروجی

فصل هفتم


ورودی و خروجی


ورودی و خروجی در اسکریپت‌های Bash مبحث پیچیده‌ایست، زیرا انعطاف‌پذیری بسیار زیادی در چگونگی انجام آن، وجود دارد. این فصل فقط یک ارائه سطحی از آنچه ممکن است، می‌باشد.

ورودی به هر اطلاعاتی که برنامه شما دریافت می‌کند(یا می‌خواند) اشاره می‌نماید. در یک اسکریپت Bash ورودی از چند محل مختلف می‌تواند برسد:

  • شناسه‌های خط فرمان(که در پارامترهای مکانی قرارگرفته‌اند)

  • متغیرهای محیطی، موروثی از هر پردازشی که اسکریپت را آغاز نموده
  • فایلها
  • هر چیز دیگری که یک توصیف‌گر فایل می‌تواند به آن اشاره کند(لوله‌ها،ترمینال‌ها، سوکت‌ها، و غیره). این موارد جلوتر بحث خواهند شد.

خروجی به هر اطلاعاتی که برنامه شما ارائه می‌کند(یا می‌نویسد) اشاره می‌کند. خروجی یک اسکریپت Bash نیز می‌تواند به چندین محل مختلف برود:

  • فایلها
  • هر چیز دیگر که یک توصیف‌گر فایل می‌تواند به آن اشاره کند
  • شناسه‌های خط فرمانی برای سایر برنامه‌ها
  • متغیرهای محیطی که به سایر برنامه‌ها ارسال می‌شوند

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


1. شناسه‌های خط فرمان

برای بسیاری از اسکریپت‌ها، اولین(یا تنها) ورودی که به آن توجه می‌نماییم، شناسه‌هایی می‌باشند که اسکریپت در خط فرمان دریافت نموده است. به طوری که در فصل پارامترها دیدیم، تعدادی پارامتر ویژه معتبر برای هر اسکریپت وجود دارد که، محتوی این شناسه‌ها هستند. اینها پارامترهای مکانی نام دارند. این پارامترها یک آرایه خیلی ساده از رشته‌ها می‌باشند که با اعداد شاخص‌گذاری شده‌اند(در حقیقت، در شل POSIX ، تنها آرایه موجود در شل هستند). به اولین پارامتر مکانی با ‎$1‎ رجوع می‌شود، به دومین، با ‎$2‎، و به همین ترتیب، پس از نهمین پارامتر، باید از ابروها برای رجوع به آنها استفاده گردد: ‎${10}, ${11}‎، و غیره. اما در عمل، خیلی به ندرت ممکن است مجبور به استفاده از این ترکیب بشوید، به علت آنکه، روشهای بهتری برای کار با آنها به عنوان یک گروه، موجود است.

علاوه بر ارجاع یک به یک ، همچنین می‌توانید به مجموعه کامل پارامترهای مکانی، با جایگزینی ‎"$@"‎ رجوع نمایید. نقل‌قول دوگانه در اینجا بینهایت مهم است. اگر از نقل‌قول دوگانه استفاده نکنید، هر کدام از پارامترهای مکانی دستخوش تفکیک و جانشینی می‌گردند. شما آن را نمی‌خواهید. با استفاده از نقل‌قول‌ها، به Bash می‌گویید که می‌خواهید هر پارامتر به صورت یک کلمه جداگانه حفظ گردد.

یک روش دیگر کارکردن با پارامترهای مکانی، دور انداختن هر یک پس از استفاده است. یک دستور داخلی ویژه‌ای به نام shift وجود دارد، که برای این منظور به کار می‌رود. موقعی که شما فرمان shift را صادر می‌کنید، اولین پارامتر مکانی (‎$1‎) از بین می‌رود. دومین پارامتر می‌شود ‎$1‎، سومی می‌شود ‎$2‎، و به همیت ترتیب تا پایان خط. بنابراین، اگر مایل باشید، می‌توانید حلقه‌ای بنویسید که استفاده از ‎$1‎ را چندین بار ادامه دهد.

در اسکریپت‌های حقیقی، ترکیبی از این تکنیک‌ها به کار می‌رود. یک حلقه برای پردازش ‎$1‎ مادامی‌که با یک علامت - شروع می‌شود آن را به عنوان گزینه تعبیر می‌کند و سپس وقتی همه گزینه‌ها به کنار رفتند، هر چیز باقیمانده (در ‎"$@"‎) نام فایلی است که می‌خواهیم پردازش کنیم.

برای اختصار، در اینجا مثالهایی از پردازش شناسه‌ها نمی‌آوریم. به جای آن، به FAQ جایی که مثالهای آنها قبلاً نوشته شده ارجاع می‌دهیم.


  • تکرار مفید:
    قبل از شروع به نوشتن، شناسایی کنید که ورودی برنامه شما از کجا می‌آید. اگر می‌خواهید اطلاعاتی را به اسکریپت خود ارسال کنید، روشی برای معنی کردن نوع اطلاعاتی که با آن سر و کار دارید، انتخاب نمایید. اگر احتیاج به ارسال نام فایلها دارید، ارسال آنها به صورت شناسه‌ها، یک رویکرد عالی است، زیرا هر یک از آنها به صورت یک کلمه بسته‌بندی می‌گردد،.



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

آرایه های انجمنی

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


آرایه‌های انجمنی

تا همین اواخر، BASH فقط از اعداد( به طور دقیق‌تر، اعداد صحیح مثبت ) می‌توانست برای شاخص آرایه‌ها استفاده کند. به این معنی که نمی‌توانستید یک رشته را با دیگری ترجمه یا ترسیم کنید . این به عنوان یک کمبود احساس می‌شد. اشخاصی به منظور آدرس‌دهی به یک موضوع، سوءمصرف از متغیرهای غیرمستقیم را آغاز کردند .

پس از انتشار BASHنگارش 4، دیگر بهانه‌ای برای استفاده از متغیر غیر مستقیم( یا بدتر از آن، eval) برای این منظور نیست. اکنون شما می‌توانید آرایه‌های انجمنی خوش‌ساخت را به کار ببرید.

برای ایجاد یک آرایه انجمنی، باید آرایه به صورت( declare -A) تعریف شود. این برای هماهنگی با تعریف آرایه‌های استاندارد شاخص گذاری شده است. در اینجا چگونگی انجام آن، آمده است:

   $ declare -A fullNames
   $ fullNames=( ["lhunath"]="Maarten Billemont" ["greycat"]="Greg Wooledge" )
   $ echo "Current user is: $USER.  Full name: ${fullNames[$USER]}."
   Current user is: lhunath.  Full name: Maarten Billemont.

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

    $ for user in "${!fullNames[@]}"
    > do echo "User: $user, full name: ${fullNames[$user]}."; done
    User: lhunath, full name: Maarten Billemont.
    User: greycat, full name: Greg Wooledge.

در اینجا دو مورد یادآوری: اول، ترتیب بازیابی کلیدها از یک آرایه انجمنی، با کاربرد ترکیب دستوری ‎${!array[@]}‎ غیرقابل پیش‌بینی است، و لزوماً به همان ترتیب که شما اعضاء را اختصاص داده‌اید، یا هر نوع ذخیره مرتب دیگر نمی‌باشد.

دوم، وقتی از پارامترها به عنوان کلید آرایه انجمنی استفاده می‌کنید، نمی‌توانید از علامت $ صرف‌نظر کنید. با آرایه‌ها شاخص‌دار معمولی،قسمت [...] در حقیقت یک مفهوم محاسباتی است( در آنجا به راستی، می‌توانید بدون یک علامت‌گذاری صریح ‎$((...))‎ محاسبه انجام دهید(. در یک زمینه محاسباتی، یک نام به هیچ وجه نمی‌تواند عدد معتبری باشد، و بنابراین BASH فرض می‌کند، آن یک پارامتر است که شما می‌خواهید از محتوای آن استفاده کنید. این مورد در آرایه‌های انجمنی صدق نمی‌کند، چون در اینجا یک نام نیز به خوبی می‌تواند یک کلید معتبر آرایه انجمنی باشد.

اجازه دهید با مثال تشریح کنیم:

    $ indexedArray=( "one" "two" )
    $ declare -A associativeArray=( ["foo"]="bar" ["alpha"]="omega" )
    $ index=0 key="foo"
    $ echo "${indexedArray[$index]}"
    one
    $ echo "${indexedArray[index]}"
    one
    $ echo "${indexedArray[index + 1]}"
    two
    $ echo "${associativeArray[$key]}"
    bar
    $ echo "${associativeArray[key]}"
    $
    $ echo "${associativeArray[key + 1]}"
    $

به طوری که می‌توانید ملاحظه کنید، هم ‎ $index‎ و هم index به خوبی با آرایه‌های معمولی کار می‌کنند. هر دو، عدد 0 ارزیابی می‌شوند. حتی می‌توانید برای اضافه کردن 1 به آن و به دست آوردن مقدار دوم، با آن محاسبه کنید. آنچه که با آرایه‌های انجمنی نمی‌تواند انجام شود. در اینجا، لازم است ‎$key‎ به کار برود، آن دیگری کار نمی‌کند.


پایان فصل ششم


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

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


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

استفاده از مزیت عناصر آرایه‌ها به راستی آسان است. به علت آنکه یک آرایه وسیله مطمئن ذخیره است، ما به سادگی می‌توانیم یک حلقه 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[*]}‎ را فقط موقعی که می‌خواهید همه عناصر آرایه را در یک رشته منفرد با یکدیگر متصل کنید، به کار ببرید.


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