آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

شناسه‌ها

Arguments

شناسه‌ها

این صفحه مقوله‌ای را تشریح می‌نماید که احتمالاً مهمترین مبحث در باره برنامه‌نویسی پوسته است و بیش از همه به طور نادرست فهمیده شده است.

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

اجرای دستورات

پوسته یک میانجی بین شما(یا اسکریپت شما) و هسته(کرنل) می‌باشد. پوسته اجازه می‌دهد شما به جای احضار مستقیم فراخوان‌های سیستمزیرنویس 1 ، دستورات را با استفاده از ترکیب دستوری مشخص شده اجرا کنید.

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

اجرای دستورات از طریق فراخوان سیستم ‎execve(2)‎ روی می‌دهد. این فراخوان به سه بخش از اطلاعات نیاز دارد:

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

جهت تخصیص یک زمینه برای برنامه و گفتن آنچه باید انجام بدهد، ما آن برنامه را با یک آرایه از شناسه‌ها آماده می‌کنیم. این یعنی، ما یک مجموعه رشته به آن می‌دهیم. هر یک از این رشته‌هامی‌تواند شامل هر کاراکتر(بایت) (به استثنای بایت ‎NUL‎) باشد. به معنای آنکه، هر شناسه می‌تواند یک کلمه، یک جمله، یا بیشتر باشد.

اگر ما برای مثال، مایل به حذف یک کتاب معین هستیم ، می‌توانیم برنامه rm را با فراهم نمودن نام مسیرهای فایلهایی که مایل به حذف آنها هستیم، فراخوانی کنیم:

    Execute File:   [ "/bin/rm" ]
    With arguments: [ "James, P.D. - Children of Men - Chapter 1.pdf" ]
                    [ "James, P.D. - Children of Men - Chapter 2.pdf" ]
                    ...

فرمان rm این دو شناسه را برای تعیین آنکه کدام فایلها باید حذف شوند به کار خواهد برد. در این حالت، هر شناسه را ‎ unlink(2)‎ خواهد نمود.

(در واقعیت، موقع احضار فراخوان سیستمی ‎execve(2)‎، ما یک شناسه فوق‌العاده نیز عبور می‌دهیم. این صفرمین شناسه نامی است که مایل هستیم به پردازش بدهیم. اینکه به طور دقیق به چه معنا می‌باشد و برای چه به کار می‌رود، تنها به طور مبهم تعریف گردیده, و با این مطلب نامربوط است. گفتن آنکه bash بعد از تفکیک کلمه، اولین قطعه(قطعه نام فرمان) را به عنوان شناسه صِفرُم به کار می‌برد کفایت می‌کند. من از این پس در اینجا هرگونه اشاره به آن را از قلم خواهم انداخت.)

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

ترکیب دستوری پوسته

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

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

برای اجرای یک فرمان ساده rm در پوسته، ما باید جمله‌ای به همین واضحی بنویسیم:

    rm myfile myotherfile

این ترکیب دستوری پوسته را آگاه خواهد نمود، که دو فایل راحذف(‎remove‎) کند: myfile، و myotherfile. چگونه پوسته این مطلب را می‌فهمد؟ چطور یک جمله را به فراخوان‌های سیستم تبدیل می‌کند؟ کلید این موضوع تفکیک کلمه می‌باشد.

تفکیک کلمه

برای یک پوسته، فضای سفید به طور غیرقابل باوری اهمیت دارد. بنابراین با این اندیشه که یک فاصله یا tab بیشتر یا کمترتفاوت زیادی ایجاد نمی‌کند، نادانی نکنید. و تصور نکنید که چون فضای سفید در C یا Java خیلی مطرح نیست، همان مطلب در پوسته شما نیز صدق می‌کند. فضای سفید برای رخصت دادن به پوسته جهت آنکه شما را درک کند ضروری است.

پوسته سطر کُد شما را می‌گیرد و آنرا از جایی که رشته‌های گرامری فضای سفید وجود دارد به تکه‌ها خُرد می‌کند. فرمان فوق به صورت زیر تفکیک می‌شود:

    rm myfile myotherfile
      ^      ^

    [rm]
    [myfile]
    [myotherfile]

به طوری که می‌توانید ببینید، تمام فضاهای سفید گرامری حذف گردیده‌اند. بعد از اینکه تفکیک کلمه روی سطر دستور شما انجام شده است، فضای سفیدی باقی نمانده است. حقیقتاً ما دارای سه تکه کاملاً جداگانه از کاراکترها می‌باشیم: یکی rm، دیگری myfile، و آخری myotherfile. حالا پوسته این تکه‌ها را برای ساختن فراخوان سیستمی‎execve(2)‎ به کار می‌برد.

پوسته از شناسه‌ها، یک آرایه برای عبور دادن به سیستم‌عامل می‌سازد. عناصر (رشته‌ها) در این آرایه، rm و myfile و myotherfile می‌باشند. یک فراخوان ‎execve(2)‎ با تحویل این آرایه احضار می‌گردد. سیستم عامل روی آن عمل می‌کند، متغیر محیطی PATH را برای برنامه‌ای به نام rm جستجو می‌کند، و آنرا با شناسه‌های داخل آرایه اجرا می‌کند. سپس rm آن فایلها را ‎unlink(2)‎ می‌کند.

(BASH به طور واقعی نخست خودش PATH را جستجو می‌کند، و محل rm را در یک hash ذخیره می‌کند. سایر پوسته‌ها ممکن است آنرا انجام ندهند، و به راستی در این لحظه این اهمیت ندارد.)

جداکننده داخلی فیلد ‎(`IFS`)‎

Bash دارای یک متغیر خاصمی‌باشد، IFS، که برای تعیین آنکه کدام کاراکترها به عنوان جداکننده‌ها تفکیک کلمه استفاده می‌شوند، به کار می‌رود. به طور پیش‌فرض، IFS برقرار نیست(unset است) و چنان عمل می‌کند که اگر به کاراکترهای فاصله، tab و سطر جدید ‎(`$' \t\n'`))‎ تنظیم می‌گردید. نتیجه این مورد آن است که شما هر یک از این اشکال فضای سفید را می‌توانید برای جدا کردن کلمات به کار ببرید.

در حین تفکیک کلمه از IFS فقط برای تفکیک کلمه داده‌ها استفاده می‌شود. برای نمونه،این مثال هیچ داده‌ای را تفکیک نمی‌کند. فقط کد اسکریپت وجود دارد. یک سطر از کد اسکریپت همواره فقط از محل فضای سفید تفکیک می‌شود:

    IFS=:
    rm myfile myother:file
      ^      ^
    [rm]
    [myfile]
    [myother:file]

از طرف دیگر، در صورت که فایلها از متغیری که بسط داده می‌شود حاصل شوند، تفکیک کلمه بر داده‌هایی که از یک متغیر ناشی می‌گردند انجام می‌شود. در این حالت محتوای IFS استفاده می‌شود:

    # .کد نامناسب‎

    IFS=:
    files='myfile myother:file'
    rm $files
      ^

    # :پس از بسط پارامتر‎
    rm myfile myother:file
      ^              ^

    [rm]
    [myfile myother]
    [file]

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

چه وقت و چرا از یک IFS سفارشی استفاده نشود

اهمیت دارد که شما خطر تغییر وضع رفتارهای پوسته را درک کنید. اگر شما IFS را ویرایش کنید، از آن به بعد تفکیک کلمه در یک حالت غیر پیش‌فرض رخ می‌دهد. برخی به شما پیشنهاد خواهند نمود که IFS را ذخیره نموده وبعداً آن را به مقدار پیش‌فرض برگردانید. سایرین پیشنهاد اجرای ‎unset IFS‎ بعد از آنکه تفکیک کلمه سفارشی را انجام داده‌اید می‌کنند.

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

    # .کد نامساعد‎

    IFS=,
    names=Tom,Jack
    for name in $names
    do ...; done
    unset IFS

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

روش صحیح برای انجام این مورد یکی از این ساختارها می‌باشد:

    # آرایه‌ها‎

    names=( Tom Jack )
    for name in "${names[@]}"

    # است read سفارشی تنها محدود به فرمان IFS تفکیک کلمه بی‌خطر(بدون بسط نام مسیر)‏‎
    IFS=, read -ra namesArray <<< "$names"
    for name in "${namesArray[@]}"

    #   while-read یک حلقه‎
    while read -rd, name

    do ...; done <<< "$names,"

به طوری که می‌توانید ببینید، تنظیم یک IFS سفارشی می‌تواند قابل استفاده باشد، فقط به بهترین وجه همراه فرمان اجرا می‌گردد، به طوری که فقط بر همان فرمان یگانه اِعمال می‌شود. تنها تعداد معینی از فرمانهای داخلی واقعاً می‌توانند از IFS به این طریق استفاده کنند. فرمان read یکی از آنها می‌باشد. شما در این روش نمی‌توانید بسط غیر نقل‌قولی را مهار کنید، اما اشکالی ندارد، زیرا از ابتدا نیز واقعاً نمی‌توانستید این کار را انجام بدهید!

    names=Tom,Jack

    # کُد نامناسب
    IFS=, namesArray=( $names )      # .را محدود کنید IFS به این طریق نمی‌توانید‎
    #     .هر دو را برای سرتا سر اسکریپت برقرار می‌کند namesArray و IFS در حقیقت‎
    IFS=,; namesArray=( $names ); unset IFS    # .کار می‌کند اما کد نامناسبی است‎
    #                             ‏تفکیک کلمه نا امن رخ می‌دهد(بسط نام مسیر ضمنی)‏‎

    # کد خوب‎
    IFS=, read -ra namesArray <<< "$names"    #  محدود 'read' فقط به فرمان IFS  ‎
    #           .می‌گردد و بدون بسط نام مسیر، نام متغیرها بدون خطر تجزیه می‌شوند‎

نقل‌قول کردن

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

اگر ما از روی بی ‌تجربگی بدون هر گونه تفکر و ملاحظه‌ای در مورد ترکیب دستوری پوسته به آن گفته بودیم، فصل اول را حذف کند، این است آنچه رخ می‌داد:

    rm James, P.D. - Children of Men - Chapter 1.pdf
      ^      ^    ^ ^        ^  ^   ^ ^       ^

    [rm]
    [James,]
    [P.D.]
    [-]
    [Children]
    [of]
    [Men]
    [-]
    [Chapter]
    [1.pdf]

پوسته شما 9 نام ‌فایل برای حذف به برنامه rm ارائه می‌کرد، که هیچکدام آنها نام فایل مورد نظر ما نبود. rm برای حذف هر ‌فایل دارای آن نامها تلاش می‌کرد. اگر شما بدشانس بودید، شاید rm بعضی از فایلهای شما را که هرگز مایل نبودید حذف گردند، بر حسب تصادف حذف می‌کرد.

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

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

تغییر چیزی از دستوری به داده لفظی دو فرآیند را در بر می‌گیرد: نقل‌قول کردن یا گریز. نقل‌قولی کردن بایت‌های ما به وسیله بسته‌بندی با علامت‌های نقل‌قول در اطراف آنها انجام می‌گردد. گریز با مقدم کردن کاراکتر گریز \ بر هر بایت انجام می‌شود.

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

    # :گریز یافته‎
    rm James,\ P.D.\ -\ Children\ of\ Men\ -\ Chapter\ 1.pdf

    # :نقل قولی شده ‎
    rm James," "P.D." "-" "Children" "of" "Men" "-" "Chapter" "1.pdf

    # :می‌توانیم با نقل‌قولی کردن تمام کاراکترهای شناسه، این سطر را زیباتر کنیم ‎
    rm "James, P.D. - Children of Men - Chapter 1.pdf"
      ^

    [rm]
    [James, P.D. - Children of Men - Chapter 1.pdf]

هر بایتی که در نقل‌قول‌های دستوری تعبیه گردد دیگر به صورت دستوری در نظر گرفته نمی‌شود(با برخی استثناهای مخصوص نقل‌قول که اکنون وارد آن نمی‌شوم). این به آن معنا می‌باشد که اگر ما رشته ‎foo bar‎ را نقل‌قولی کنیم، هر کاراکتر در آن رشته هرگونه معنی و مقصود برای پوسته را از دست خواهد داد. پوسته آنها را مانند کاراکترهای معمولی می‌بیند و آنها را همراه با قطعه‌ای که در حال کار روی آنست عبور می‌دهد.

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

برای اطلاعات بیشتر در باره نقل‌قول‌ها و اینکه آنها دقیقاً چطور رفتار می‌کنند، صفحه نقل‌قول‌ها را ببینید.

بسط پارامترها

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

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

متغیرها نوعی پارامتر می‌باشند. آنها پارامترهایی با نام مشخص می‌باشند و برای تخصیص داده‌ها آسان هستند. نام یک متغیر تنها می‌تواند شامل کاراکترهای الفبایی-عددی(و به طور اختیاری، یک خط زیر) باشد. نام شامل علامت دلار نیست.

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

    $ place=lawn
    $ echo Welcome to my $place.
    Welcome to my lawn.

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

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

اگر پارامتری که داده‌هایش شامل فضای سفید است را بدون نقل‌قولی نمودن بسط بدهیم، این است آنچه اتفاق می‌افتد:

    book="Children of Men.pdf"
    rm $book

    # :پس از بسط پارامتر‎
    rm Children of Men.pdf
      ^        ^  ^

    [rm]
    [Children]
    [of]
    [Men.pdf]

تفکیک کلمه بعد از PE انجام می‌شود

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

    book="Children of Men.pdf"
    rm "$book"

    # :بعد از بسط پارامتر‎
    rm [Children of Men.pdf]  
      ^  # کُد کاذب هستند،آنها واقعاً آنجا نیستند، بلکه نماد هستند ‎[‎ و ‎]‎
         # که این بایتها توسط نقل‌قولهای فوق به عنوان لفظی علامت خورده بودند‎
    [rm]
    [Children of Men.pdf]

نقل‌قول کردن قبل از PE انجام می‌شود

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

    book='"Children of Men.pdf"'
    rm $book

    # :بعد از بسط پارامتر
    rm "Children of Men.pdf"
      ^         ^  ^
 #  راننوشتم ‎[‎ و ‎]‎ ‎ نقل‌قول‌ها در اینجا لفظی هستند، نه دستوری. من ‎
 #  فوق وجود نداشت rm چون نقل‌قول دستوری در فرمان ‎
    [rm]
    ["Children]
    [of]
    [Men.pdf"]

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

نتیجه

شاید این مبحث برای اینکه تمام آن را به یکباره اخذ کنید و خوب بفهمید اندکی زیاد باشد. اگر فکر می‌کنید بعداً برگشت به این صفحه و خواندن مجدد آن به شما کمک خواهد نمود، لطفاً این صفحه را نشانه‌گذاری( bookmark) کنید.

برای ساده، بادوام و اطمینان بخش نمودن امور برای خود، شما باید راهنمایی‌های زیرین را دنبال نمایید:

  • "نقل‌قول" کردن هر شناسه‌ای که محتوی داده‌هایی است که پیش می‌آید ترکیب دستوری پوسته نیز باشند.

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

  • سعی نکنید نقل‌قول‌های دستوری در داخل پارامترها قرار بدهید. عمل نمی‌کند.

و برخی نکات مرتبط اضافی:

  • اگر به ذخیره اقلام چندگانه همراه یکدیگر نیاز دارید، از یک آرایه استفاده کنید:

     files=( 1.pdf 2.pdf "1 and a half.pdf" )
     rm "${files[@]}"
  • سعی نکنید دستورات را داخل پارامترها قرار دهید، نمی‌توانید شناسه‌ها را به طور صحیح نقل‌قولی کنید. در عوض از تابع استفاده کنید:

     search() { cd /foo; find . -name "$1"; }
     search '*.pdf'; search '*.jpg'


CategoryShell

شناسه‌ها (آخرین ویرایش ‎‎2012-01-09 15:55:00‎ توسط static-74-101-128-34)


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