توصیفگرهای فایل (به طور کوتاه: FDها) روشی برای ارجاع برنامهها به فایلها، یا منابع دیگری که همانند فایلها کارمیکنند( از قبیل لولهها،دستگاهها، سوکتها، یا ترمینالها ) میباشند. FDها نوع مشابه اشارهگرها به منابع داده، یا محلهایی که اطلاعات میتوانند نوشته شوند، هستند. موقعی که چیزی از آن FD, خوانده یا در آن نوشته میشود، داده در حال نوشته شدن در منبع FD یا خوانده شدن از آن میباشد.
به طور پیشفرض، هر فرایند جدیدی با سه FD آغاز میشود. به این توصیفگرهای فایل با نامهای ورودی استاندارد، خروجی استاندارد و خطای استاندارد رجوع میشود.در حالت کوتاه شده به ترتیب
اجازه بدهید کمی این تعاریف را محسوستر کنیم. در اینجا یک نمایش تجربی از چگونگی کار ورودی استاندارد و خروجی استاندارد میآوریم:
$ 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 دستوری است که اطلاعات را از
پس
$ rmsecrets rm: cannot remove `secrets': No such file or directory
بدون داشتن فایلی به نام
به خاطر داشته باشید موقعی که اسکریپتها را ایجاد میکنید،شما باید پیغام خطاهای سفارشی خود را به توصیفگر
echo "Uh oh. Something went really bad..">& 2
توصیفگر فایل: یک شاخص عددی ارجاع به یکی از فرآیندهای فایل باز است. هر دستوری حداقل سه توصیفگر اصلی دارد: FD شماره 0،
هر برنامهای اطلاعات، منابع، امتیازها و محدودیتهایی از پردازش والد خود به ارث میبرد. ( برای بحث پیشرفتهتر در این موضوع، بخش مدیریت پردازش را ملاحظه کنید.)یکی از آن منابع، مجموعهای از متغیرها به نام متغیرهای محیط میباشند.
در Bash, متغیرهای محیط تا اندازه بسیار زیادی مشابه متغیرهای معمولی مورد استفاده ما، کار میکنند. تنها تفاوت واقعی، آن است که آنها قبلاً، موقعی که اسکریپت شروع به اجرا میکند، مقرر شدهاند، ما خودمان نباید به آنها مقداردهی کنیم.
به طور سنتی، متغیرهای محیط نامهایی تماماً با حروف بزرگ دارند، از قبیل
ارسال اطلاعات به برنامهها از طریق متغیرهای محیط، در بسیاری موقعیتها سودمند است. یکی از آنها اولویتهای کاربر است. در سیستمهای یونیکسی، همه کاربران علایق و بیعلاقگیهای یکسان در برنامههای کاربردی ندارند، و در برخی موارد، ممکن است همه به یک زبان صحبت نکنند. بنابراین، برای کاربران سودمند خواهد بود که به هر برنامه بگویند کدام ویرایشگر مورد علاقه آنها برای اجرا میباشد(متغیر محیطی
متغیرهای محیط همچنین میتوانند به طور بینهایت آسانی در حین کار تنظیم گردند( آسانتر از آنکه اگر همان اطلاعات در یک فایل ذخیره شده باشند). موقعی که در Bash دستوری را اجرا میکنید، گزینهای دارید، برای تعیین یک تغییر موقتی محیط که فقط در طول مدت اجرای آن فرمان مؤثر است. این با قرار دادن عبارت
$ 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
محیط موقتی
اگر میدانید که برخی اطلاعات در یک متغیر محیط ذخیره شده است، در اسکریپت، میتوانید درست مانند سایر متغیرها از آن استفاده کنید:
if [[ $ DISPLAY ]] xterm; then-e top else topfi
این مثال، در صورتی که متغیر محیطی
اگر میخواهید اطلاعاتی را در متغیر محیطی قرار دهید که به پردازشهای فرزند به ارث برسد، فرمان export را به کار ببرید:
exportMYVAR = something
بخش دشوار مطلب در اینجا آنست که تغییرات محیط شما فقط برای فرزندان موروثی خواهد بود. نمیتوانید محیط یک برنامه را که از قبل در حال اجراست، یا شما آن را شروع نکردهاید، تغییر دهید.
تغییر محیط و سپس اجرا، برای برخی برنامهها به شدت رایج میباشد. اسکریپتی که این کار را به عنوان وظیفه اصلیاش انجام میدهد یک WrapperScript مینامند.
در اسکریپتهای خود از نامهای تماماً با حروف بزرگ برای متغیرها استفاده نکنید. برای پرهیز از تصادمات، حروف کوچک یا ترکیبی از کوچک و بزرگ به کار ببرید .
من سعی میکنم اسکریپتی بنویسم که دایرکتوری جاری را تغییر دهد( یا یک متغیر را تنظیم کند)، اما بعد از به پایان رسیدن اسکریپت، در همان جایی هستم که از آنجا شروع کرده بودم(یا متغیر من موجود نیست)!
فهرست مطالب
ورودی و خروجی در اسکریپتهای Bash مبحث پیچیدهایست، زیرا انعطافپذیری بسیار زیادی در چگونگی انجام آن، وجود دارد. این فصل فقط یک ارائه سطحی از آنچه ممکن است، میباشد.
ورودی به هر اطلاعاتی که برنامه شما دریافت میکند(یا میخواند) اشاره مینماید. در یک اسکریپت Bash ورودی از چند محل مختلف میتواند برسد:
شناسههای خط فرمان(که در پارامترهای مکانی قرارگرفتهاند)
هر چیز دیگری که یک توصیفگر فایل میتواند به آن اشاره کند(لولهها،ترمینالها، سوکتها، و غیره). این موارد جلوتر بحث خواهند شد.
خروجی به هر اطلاعاتی که برنامه شما ارائه میکند(یا مینویسد) اشاره میکند. خروجی یک اسکریپت Bash نیز میتواند به چندین محل مختلف برود:
ورودی و خروجی، نان و پنیر اسکریپتنویسی پوسته هستند. معین کردن اینکه ورودی شما ازکجا میآید، چگونه به نظر میرسد، و شما برای بدست آوردن خروجی مطلوب خود، چه کاری باید روی آن انجام بدهید، هسته مرکزی احتیاجات تقریباً تمام اسکریپتها میباشند.
برای بسیاری از اسکریپتها، اولین(یا تنها) ورودی که به آن توجه مینماییم، شناسههایی میباشند که اسکریپت در خط فرمان دریافت نموده است. به طوری که در فصل پارامترها دیدیم، تعدادی پارامتر ویژه معتبر برای هر اسکریپت وجود دارد که، محتوی این شناسهها هستند. اینها پارامترهای مکانی نام دارند. این پارامترها یک آرایه خیلی ساده از رشتهها میباشند که با اعداد شاخصگذاری شدهاند(در حقیقت، در شل POSIX ، تنها آرایه موجود در شل هستند). به اولین پارامتر مکانی با
علاوه بر ارجاع یک به یک ، همچنین میتوانید به مجموعه کامل پارامترهای مکانی، با جایگزینی
یک روش دیگر کارکردن با پارامترهای مکانی، دور انداختن هر یک پس از استفاده است. یک دستور داخلی ویژهای به نام shift وجود دارد، که برای این منظور به کار میرود. موقعی که شما فرمان shift را صادر میکنید، اولین پارامتر مکانی (
در اسکریپتهای حقیقی، ترکیبی از این تکنیکها به کار میرود. یک حلقه برای پردازش
برای اختصار، در اینجا مثالهایی از پردازش شناسهها نمیآوریم. به جای آن، به FAQ جایی که مثالهای آنها قبلاً نوشته شده ارجاع میدهیم.
قبل از شروع به نوشتن، شناسایی کنید که ورودی برنامه شما از کجا میآید. اگر میخواهید اطلاعاتی را به اسکریپت خود ارسال کنید، روشی برای معنی کردن نوع اطلاعاتی که با آن سر و کار دارید، انتخاب نمایید. اگر احتیاج به ارسال نام فایلها دارید، ارسال آنها به صورت شناسهها، یک رویکرد عالی است، زیرا هر یک از آنها به صورت یک کلمه بستهبندی میگردد،.
چگونه میتوانم شناسههای( گزینههای ) خطفرمان را به آسانی مدیریت کنم؟
تا همین اواخر، BASH فقط از اعداد( به طور دقیقتر، اعداد صحیح مثبت ) میتوانست برای شاخص آرایهها استفاده کند. به این معنی که نمیتوانستید یک رشته را با دیگری ترجمه یا ترسیم کنید . این به عنوان یک کمبود احساس میشد. اشخاصی به منظور آدرسدهی به یک موضوع، سوءمصرف از متغیرهای غیرمستقیم را آغاز کردند .
پس از انتشار BASHنگارش 4، دیگر بهانهای برای استفاده از متغیر غیر مستقیم( یا بدتر از آن، eval) برای این منظور نیست. اکنون شما میتوانید آرایههای انجمنی خوشساخت را به کار ببرید.
برای ایجاد یک آرایه انجمنی، باید آرایه به صورت( declare
$ 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.
در اینجا دو مورد یادآوری: اول، ترتیب بازیابی کلیدها از یک آرایه انجمنی، با کاربرد ترکیب دستوری
دوم، وقتی از پارامترها به عنوان کلید آرایه انجمنی استفاده میکنید، نمیتوانید از علامت
اجازه دهید با مثال تشریح کنیم:
$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]} " $
به طوری که میتوانید ملاحظه کنید، هم
استفاده از مزیت عناصر آرایهها به راستی آسان است. به علت آنکه یک آرایه وسیله مطمئن ذخیره است، ما به سادگی میتوانیم یک حلقه for را برای تکرار روی عناصر آن، به کار ببریم:
$for file in "$> { myfiles [@]} ";do > cp"$ /backups/ >file "done
به ترکیب دستوری استفاده شده برای بسط آرایه در اینجا توجه نمایید. ما شکل نقلقولی به کار بردهایم:
دو مثال زیر نتیجه یکسان دارند:
$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
مثال اول یک آرایه به نام
به خاطر داشته باشید، بسط
مثال فوق آرایه را در یک ساختار حلقه
myfiles =( cpdb.sql home.tbz2 etc.tbz2 )"$ /backups/{ myfiles [@]} "
این مثال، دستور cp را، با تعویض عبارت
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] } "
( میتوانید آرایهای بدون عضو شماره صفر ایجاد کنید. آنچه قبلاً در مورد آرایههای پراکنده گفتیم را به خاطر بیاورید --شما میتوانید بین شاخصها حفره داشته باشید--، و این مطلب در ابتدای آرایه نیز به همان خوبی صدق میکند. این وظیفه شما به عنوان برنامهنویس است که بدانیدکدامیک از آرایههای شما به طور بالقوه پراکنده است، و کدامیک اینطور نیست.)
روش دیگری نیز برای بسط تمام عناصر آرایه وجود دارد، که به شکل "
$names =( "Bob" "Peter" " $ USER " "Big Bad John") $ echo "Today's contestants are:$ { names [*] } "Today's contestants are: Bob Peter lhunath Big Bad John
توجه نمایید که در رشته حاصل شده، راهی برای گفتن آنکه نامها، کجا شروع و کجا ختم گردیدهاند، وجود ندارد! این است چرایی آنکه، هر چیزی را تا آنجا که ممکن است، جدا نگاه میداریم.
به خاطر داشته باشید، هنوز هم به دقت نقلقولی نمایید! اگر
میتوانید متغیر
$names =( "Bob" "Peter" " $ USER " "Big Bad John") $( echo "Today's contestants are:IFS =,;$ { names [*] } ") Today's contestants are: Bob,Peter,lhunath,Big Bad John
توجه نمایید که در این مثال، چگونه جمله IFS=,; echo ... را با قرار دادن بین
افسوس، بسط "
فرمان printf در اینجا سزاوار یک یادآوری میباشد، زیرا روش فوق العاده برازنده نسخه برداری از یک آرایه است:
$names =( "Bob" "Peter" " $ USER " "Big Bad John") $ printf"%s\n" "$ { names [@] } "Bob Peter lhunath Big Bad John
البته یک حلقه
$ printf"%s\0" "$ { myarray [@] } "> myfile
یک نکته پایانی: شما میتوانید تعداد عناصر یک آرایه را با استفاده از
$array =( a b c ) $ echo ${ # array [@]} 3
تکرار مفید:
همیشه بسط آرایهها را به طور صحیح نقلقولی کنید، درست همانطور که بسط پارامترهای معمولی را نقلقولی میکنید .
از