Page 1

!" #

&'( $ % )

* + , -!


‫محیط برنامه سازی لینوکس‬

‫‪1/322‬‬

‫فصل یک ‪ :‬لینوکس براي مبتدیان‬ ‫يونیکس چیست؟ به معنای دقیق ‪ ،‬اين برنامه هسته سیستم عامل اشتراك زماني‪ ،‬است‪ ،‬يعني برنامه‌ای که منابع کامپیوتر را کنترل مي‌کند‬

‫و آنها را در بین کاربرانش ‪ ،‬تخصیص مي‌دهد‪ .‬اين برنامه به کاربرانش اجازه مي دهد که برنامه‌هايشان را اجراء کنند‪ ،‬و وسايل جانبي‬

‫(ديسکها‪ ،‬پايانه‌ها ‪ ،‬چاپگر و از اين قبیل وسايل) را که به سیستم ارتباط دارد را کنترل مي‌کند و فايل سیستمي را فراهم مي‌آورد که‬

‫ذخیره سازی طولني مدت اطلعاتي همچون ‪ :‬برنامه‌ها‪ ،‬داده‌ها و اسناد را کنترل کند‪ .‬به معنای کلي‪ ،‬يونیکس غالباً نه تنها شامل اساس‬ ‫و شالوده است بلکه‪ ،‬شامل برنامه‌های ضروری همچون ‪ :‬مترجم (مفسر) ‪ ،‬ويراستار‪ ،‬زبانهای فرمانها ‪ ،‬برنامه‌هايي جهت کپي و چاپ‬

‫فايلها و از اين قبیل خدمات است‪ .‬باز هم به معنای وسیعتر‪ ،‬يونیکس حتي شامل برنامه‌های توسعه يافته توسط شما و يا ديگر کاربراني‬

‫است که اين برنامه‌ها را در سیستم شما‪ ،‬بدون وقفه اجراء مي‌شوند‪ ،‬برنامه‌هايي همچون ‪ :‬ابزارهايي برای تهیه اسناد‪ ،‬مراحلي برای‬

‫تجزيه تحلیل آماری و بسته‌های نرم افزاری تصاوير (طرحها)‪ .‬کدامیك از اين استفاده‌هايي که از سیستم يونیکس مطرح شد‪ ،‬با توجه به‬

‫سیستمي که شما در حال استفاده از آن هستید‪ ،‬صحیح است‪ .‬زماني که ما از اصطلح يونیکس در مابقي اين کتاب استفاده مي‌کنیم‪،‬‬

‫محتوای کتاب بايد آن معني را که ضمني است‪ ،‬مطرح کند‪ .‬سیستم يونیکس بعضي اوقات درمقايسه با آنچه که هست ‪ ،‬مشکل تر به نظر‬ ‫مي‌رسد‪ ،‬يعني برای مبتديان درك چگونگي بهترين استفاده از امکانات موجود‪ ،‬مشکل است‪ .‬اما خوشبختانه‪ ،‬شروع کار با آن سخت‬

‫نیست‪ ،‬تنها اطلع و دانش پیرامون چندين برنامه باعث راه افتادن شما در استفاده از اين سستم مي‌شود‪ .‬اين فصل وسیله‌ای است برای‬ ‫کمك به شما در جهت شروع هر چه سريعتر استفاده از سیستم‪ .‬اين فصل به عنوان بررسي کلي است نه راهنمای استفاده‪ ،‬ما در نظر‬

‫داريم که مطالب را به صورت جزئي‌تر در فصول بعدی دوباره‪ ،‬مطرح کنیم‪ .‬ما در نظر داريم که در مورد اين عرصه‌های وسیع صحبت‬

‫کنیم ‪:‬‬

‫•مباني اصلي ‪ :‬شامل وارد شدن و خارج شدن از سیستم‪ ،‬فرامین ساده‪ ،‬تصحیح خطاهای تايپ‪ ،‬پست الکترونیکي‪،‬‬ ‫ارتباطات بین پايانه‌ای ‪ ،‬است‪.‬‬

‫•استفادة روز به روز‪ ،‬شامل موارد زير است ‪ :‬شامل ‪ ،‬فايلها و فايل سیستم‪ ،‬فايلهای چاپگر‪ ،‬فهرست راهنماها ‪ ،‬فرامین مورد‬ ‫استفاده عادی‪.‬‬

‫•فرمان مترجم (مفسر) يا ‪ shell‬شامل موارد زير است ‪:‬‬

‫مختصر نويسي نام فايل‪ ،‬تغییر جهت ورودی و خروجي ‪ ، Pipes ،‬پاك کننده‌های محیط و از بین بردن نمادها و تعريف مسیر جستجو‬ ‫برای فرامین‪.‬‬

‫اگر شما از يك سیستم يونیکس استفاده مي‌کنید‪( ،‬از آنجايي که اغلب قسمتهای اين فصل برای شما آشنا است) مستقیماً به سراغ فصل‬

‫‪ 2‬برويد‪ .‬شما به يك کپي از فهرست راهنمای برنامه‌ساز يونیکس نیاز خواهید داشت‪ ،‬حتي زماني که شما اين فصل را مطالعه مي‌کنید‪،‬‬

‫غالبا ً بیان اين امر که بهتر است‪ ،‬حتي زماني که شما اين فصل را مطالعه‌ مي‌کنید‪ ،‬غالبا ً بیان اين امر که بهتر است شما برخي از مطالب‬

‫موجود در فهرست را به جای تکرار آنها در اينجا مورد مطالعه قرار دهید‪ ،‬برای ما امری آسانتر به نظر مي رسد‪ .‬اين کتاب در نظر ندارد‬

‫که آن مطالب را جايگزين کند‪ ،‬بلکه در نظر دارد که به شما چگونگي بهترين استفاده از فرامین توصیف شده در آن‪ ،‬را نشان دهد‪ .‬علوه‬ ‫بر اين‪ ،‬ممکن است تفاوتهای بین آنچه که ما در اينجا مي‌گوئیم و آنچه که در سیستم شما صحیح به نظر مي‌رسد‪ ،‬وجود داشته باشد‪.‬‬

‫فهرست راهنما‪ ،‬در شروع آنچه که برای يافتن برنامه‌های صحیح جهت کاربرد در رفع مشکل و فراگیری استفاده از آن‪ ،‬ضروری به نظر‬

‫مي‌رسد‪ ،‬دارای فهرست جابه‌جا شده‌ای است‪ .‬نهايتاً ‪ ،‬يك توصیه‌ای که لزم به نظر مي‌رسد اين است که از آزمايش کردن ‪ ،‬نترسید ‪ .‬اگر‬


‫محیط برنامه سازی لینوکس‬

‫‪2/322‬‬

‫شما يك مبتدی هستید‪ ،‬مسائل تصادفي زيادی وجود دارد که شما مي‌توانید با انجام آنها به خودتان يا ديگر کاربران آسیب برسانید‪.‬‬ ‫بنابراين‪ ،‬چگونگي عملکرد آن مسائل را با تلش و کوشش بر روی آنها فرا گیريد‪ .‬اين فصل‪ ،‬فصل بسیار طولني است و بهترين راه‬ ‫برای مطالعه آن اين است که هر دفعه چند صفحه را مطالعه کنید و مادامي که به پیش مي‌رويد‪ ،‬مطالب را مورد آزمايش و بررسي قرار‬ ‫دهید‪.‬‬

‫بخش ‪ 1  .1‬شروع كار‬ ‫برخي از مقدمات در مورد پايانه‌ها و تايپ به منظور اجتناب از تشريح هر مورد پیرامون استفاده از کامپیوترها‪ ،‬ما بايد فرض کنیم که‬

‫شما ‌ آشنايي مخصتری با پايانه‌های کامپیوتر و چگونگي استفاده از آنها داريد‪ .‬در صورتي که هر کدام از جملت زير مبهم و پیچیده‬

‫باشد‪ ،‬ما بايد به منظور درك آن از کارشناس سؤال کنیم‪ .‬سیستم يونیکس‪ ،‬سیستم دو طرفه کامل است‪ ،‬يعني علئم و حروفي که شما از‬

‫طريق صفحه کلید‪ ،‬تايپ مي‌کنید به سیستم انتقال پیدا مي‌کند‪ ،‬به نحوی که سیستم آنها را به پايانه‌ها به منظور چاپ بر روی صفحه‬

‫نمايش‪ ،‬بر مي‌گرداند‪ .‬به طور طبیعي‪ ،‬اين فرايند انعکاس‪ ،‬علئم و حروف را به طور مستقیم در صفحه نمايش‪ ،‬کپي مي‌کند ‪ ،‬بنابراين‬

‫شما مي‌توانید آنچه را که شما در حال تايپ آن هستید را ببنید اما‪ ،‬بعضي اوقات همچون زماني که شما در حال تايپ يك کلمه رمز‬

‫هستید‪ ،‬فرايند انعکاس قطع مي‌شود‪ ،‬بنابراين علئم و حروف بر روی صفحه نمايش‪ ،‬نمايان نمي‌شود‪ .‬اغلب علئم و حروف صفحه‬ ‫کلید‪ ،‬بدون هیچ مفهوم خاصي از جمله علئم چاپي معمولي و رايج به شمار مي‌آيند‪ ،‬اما تعداد کمي از آنها به کامپیوتر چگونگي تفسیر‬

‫تايپ شما را اعلم مي‌کند‪ .‬به مراتب‪ ،‬مهمترين اين موارد‪ ،‬کلید ‪ Return‬است‪ .‬کلید ‪ Return‬به معنای پايان خط ورودی است‪ ،‬سیستم‬ ‫اين معنا را با حرکت مکان نما پايانه به ابتدای خط بعدی در صفحه نمايش‪ ،‬منعکس مي‌سازد‪ .‬کلید ‪ Return‬بايد قبل از اينکه سیستم‬

‫بخواهد علئمي که شما تايپ کرده‌ايد را تفسیر و تعبیر کند‪ ،‬فشار داده شود‪ .‬کلید ‪ Return‬نمونه‌ای از علئم کنترلي است‪ ،‬يعني يك‬ ‫علمت غیر قابل رؤيتي که برخي از جنبه‌های ورودی ـ خروجي را برروی پايانه‌ها‪ ،‬کنترل مي‌کند‪ .‬بر روی هر کدام از پايانه‌های مستدل‬

‫(منطقي)‪ Return ،‬دارای يك کلید مخصوص به خود است‪ .‬اما اغلب علئم کنترلي چنین نیستند‪ .‬در عوض آنها بايد به وسیله پايین نگه‬ ‫داشتن کلید ‪ Control‬تايپ شوند‪ ،‬بعضي اوقات تحت عنوان ‪ Ctl‬يا ‪ CNTL‬يا ‪ CL RL‬از آنها ياد مي‌شود‪ .‬بعد از آن‪ ،‬کلید ديگری را‬

‫فشار دهید که معمول ً آن کلید شامل يك حرف است ‪ .‬برای مثال ‪ »Return « :‬ممکن است به وسیله فشار دادن کلید ‪ Return‬يا‬

‫شرايط مشابه به آن يا پايین نگه داشتن کلید ‪ Contrl‬و تايپ’‪ ‘m‬تايپ شود‪ .‬بنابراين ‪ Return‬ممکن است شامل ‪ CTl-d‬باشد که بیان‬ ‫کنندة برنامه‌ايي است که ديگر شامل ورودی نیست‪ CTl-g ،‬که شامل صدای زنگ موجود بر روی پايانه‌ها است‪ CTl-h ،‬غالبا ً ‪ ،‬کلید‬

‫‪ backspace‬نامیده مي‌شود که مي‌تواند به منظور تصحیح خطاهای کپي به کار برده شود و ‪ CTL-I‬که غالباًُ کلید ‪ Tab‬نامیده مي‌شود‬

‫که مکان‌نما را به نقطه ‪ Tab‬بعدی به جلو مي‌برند‪ ،‬که اين فرايند بیشتر شبیه به ماشین تحرير تنظیمي‪ ،‬عمل مي‌کند‪ .‬نقطه ‪ Tab‬در‬

‫سیستمهای يونیکس به اندازه هشت (‪ )8‬کاراکتر از يکديگر فاصله دارند‪ .‬هر دو علمت ‪ backspace‬و ‪ Tab‬در اغلب پايانه‌ها دارای‬

‫کلیدهای مخصوص به خود هستند‪.‬دو کلید ديگر وجود دارد که دارای معنای مشابه به يکديگر مي‌باشد‪ .‬کلید ‪ delete‬که بعضي اوقات‬ ‫‪ rub-out‬يا برخي ديگر از علئم اختصاری و ‪ break‬نامیده میشوند‪ ،‬و بعضي اوقات ‪ interrupt‬نامیده مي‌شوند‪ .‬در اغلب سیستمهای‬ ‫يونیکس ‪ ،‬کلید ‪ delete‬بدون لحظه‌ای درنگ برای پايان دادن برنامه‪ ،‬آن را بلفاصله متوقف مي‌سازد‪ .‬در برخي از سیسمتها‪CTL-c ،‬‬

‫اين کار را انجام مي‌دهد‪ .‬و در برخي از سیستمها‪ ،‬با توجه به اين نکته که پايانه‌ها چگونه متصل مي‌شوند‪ ،‬کلید ‪ break‬برای ‪ delete‬يا‬

‫‪ CTL-c‬به عنوان کلیدی هم معنا و دارای همان فعالیت‪ ،‬معرفي مي‌شود‪.‬‬


‫محیط برنامه سازی لینوکس‬

3/322

‫بحث پیرامون يونیکس‬ ‫ آنچه را که‬، ‫ از طريق مثالهای موجود در اين کتاب‬،‫ بحث را آغاز کنیم‬، ‫اجازه دهید که با گفتگويي پیرامون شما و سیستم يونیکس تان‬

‫ پاسخهای کامپیوتر به صورت علئمي به سك ماشین تحرير است و‬، ‫شما تايپ کرده‌ايد در حروفهايي به صورت موب چاپ شده است‬ ‫توضیحات و تعريف به صورت موب است‬

: ‫ سیستمتان بايد اين موارد را اعلم کند‬.‫ شماره ای بگیريد يا دکمه‌ای را در صورت لزوم روشن کنید‬: ‫ارتباطي را ايجاد کنید‬

Establish a connection: dial a phone or turn on a switch as necessary. Yoyr system should say login: You Type your name, then press RETURN password: your password won`t be echoed as youe type it you have mail. There`s mail to be read after you lig in $ The system is now rady for your commands $ press RETURN a couple of times $ date What` the dte and time? sun sep 25 23:02::57 EDT 1983 $ who who`s using the machine? jlp tty0 sep 25 13:59 you tty2 sep 25 23:01 mary tty4 sep 25 19:03 doug tty5 sep 25 19:22 egb tty7 sep 25 17:17 bob tty8 sep 25 20:48 $ mail Read your mail From doug sun sep 25 20:53 EDT 1983 give me a call sometime monday ? RETURN moves on to the next message from mary sun sep 25 19:07 EDT 1983 Next message Lunch at noon tomorrow? ?d Delete this message $ No more this message $ mail mary send mail to mary lunch at 12 is fine ctl-d End of mail $ Hang up phone or turn off terminal and that`s the end ‫ مابقي اين بخش‬. ‫ همانگونه که بسیاری از افراد چنین مي‌کند‬،‫بعضي اوقات تمام مواردی که در اينجا بیان شد شامل يك مرحله است‬

. ‫ بحث مي‌کند‬،‫در مورد قسمت بال به علوه يدگر برنامه‌هايي که آن برای انجام کارهای مفید ممکن مي‌سازد‬


‫محیط برنامه سازی لینوکس‬

‫‪4/322‬‬

‫ورود به سيستم‬ ‫شما بايد يك نام و يك کلمه رمز ورودی داشته باشید‪ ،‬شما مي‌توانید اين نام را از اسم يا برنامه نرم‌افزاری سیستم‌تان بگیريد‪ .‬سیستم‬ ‫يونیکس قابلیت ارتباط با انواع وسیع پايانه‌ها را دارد‪ ،‬اما اين سیستم به طرز قابل توجهي در جهت ابزارهايي با حروف کوچك است‪،‬‬

‫يعني حروفي که مطالب را از يکديگر مجزا مي سازد‪ ،‬اگر پايانه شما تنها حروف بزرگ ايجاد کند‪( ،‬مثل برخي از ويدئو و پايانه های‬

‫قابل حمل) زندگي آنچنان سخت خواهد شد که شما بايد به دنبال پايانه ديگری باشید‪ .‬از دکمه‌هايي که به طرز مناسبي بر روی وسیله‬

‫شما قرار گرفته است‪ ،‬مطمئن شويد‪ ،‬از حروف بزرگ و کوچك‪ ،‬سیستم دو طرفه کامل و ديگر تجهیزاتي که کارشناسان به آنها توصیه‬ ‫مي‌کندن‪ ،‬مثل سرعت يا سرعت باود نیز اطمینان حاصل کنید‪ .‬با استفاده از هر عمل شگفت‌انگیزی که برای پايانه شما نیاز است‪،‬‬

‫ارتباطي را ايجاد کنید‪ ،‬اين فرايند ممکن است شامل ارتباط تلفني يا صرفا ً ضربه زدن به يك دکمه باشد‪ .‬در موارد ديگر‪ ،‬سیستم بايد‬ ‫عمل تايپ را انجام دهد‪.‬‬

‫برقراري ارتباط‬ ‫اگر سیستم اطلعات غیرمفید‪ ،‬تايپ کند‪ ،‬احتمال ً نشان دهنده اين است که شما سرعت غلطي را انتخاب کرده‌ايد‪ ،‬محیط مربوط به‬

‫سرعت را و نیز ديگر دکمه‌ها را چك کنید‪ .‬اگر اين کار فايده نداشت‪ ،‬کلید ‪ break‬يا ‪ interrupt‬را چند بار آهسته ‪ ،‬فشار دهید‪ .‬اگر‬

‫هیچکدام از اين کارها پیام ارتباط را نمايان نکرد‪ ،‬فرد متخصصي را به کمك بگیريد ‪ .‬زماني که شما ارتباط برقرار کرديد‪ ،‬پیامي به اين‬ ‫مضمون نمايان مي‌شود ‪:‬‬

‫اسم ارتباط‌تان را با حروف کوچك تايپ کنید‪ .‬به دنبال آن‪ ،‬کلید ‪ Return‬را فشار دهید ‪ .‬اگر کلمه رمز نیاز باشد‪ ،‬در مورد آن از شما‬

‫سؤال مي‌کند و عمل چاپ مادامي که شماآن را (کلمه رمز) تايپ مي‌کنید قطع مي‌شود‪ .‬حداکثر تلشهای برقراری ارتباط‌تان به صورت‬ ‫پیام واره انجام مي شود‪ .‬معمولً به صورت يك علمت تنها‪ ،‬پیام واره نشان دهنده اين است که سیستم برای پذيرش فرامیني از جانب‬

‫شما آماده است‪ .‬پیام واره غالبا ً شبیه يك علمت دلر ‪ $‬يا علمت درصد (‪ )%‬است‪ .‬پیام واره به وسیله برنامه‌ای که مترجم (مفسر)‬

‫پیامها يا ‪ shell‬نامیده م‌شود‪ ،‬چاپ مي شود که اين برنامه واسط اصلي شما برای سیستم به شمار مي‌آيد‪ .‬شايد پیامي از روز قبل از پیام‬

‫کنوني موجود باشد يا اطلعیه ای مبني بر اين که شما نامه داريد وجود داشته باشد‪ .‬شايد بپرسید که شما اکنون در حال استفاده از چه‬ ‫نوع پايانه‌ای هستید؟ پاسخ شما به سیستم برای استفاده از هر گونه خصوصیات که پايانه آنها را داراست‪ ،‬کمك مي‌کند‪.‬‬

‫تايپ فرامين‬ ‫زماني که شما پیام واره ای را دريافت مي‌کنید‪ ،‬مي‌توانید فرامیني را تايپ کنید که اين فرامین عبارتند از درخواستهايي که سیستم آنها را‬ ‫انجام مي دهد‪ .‬ما در نظر داريم که از برنامه ها به عنوان برنامه‌هايي هم معنا و مشابه فرامین استفاده کنیم‪ .‬سیستم بايد با زمان و تاريخ‬ ‫پاسخ دهد‪ .‬سپس پیام ديگری را چاپ کند‪ ،‬بنابراين تمام مذاکرات شبیه به اين مورد در پايانه شما خواهد بود ‪:‬‬

‫‪$ date‬‬


‫محیط برنامه سازی لینوکس‬

‫‪ Return‬را فراموش نکنید و ‪ $‬را تايپ نکنید‪.‬‬

‫‪5/322‬‬

‫‪Mon sep 26 12:2057 EDT 1983‬‬ ‫‪$‬‬

‫اگر فکر مي‌کنید که عمل را اشتباه انجام داده‌ايد‪ ،‬کلید ‪ Return‬را فشاردهید‪ ،‬در اين مرحله بايد اتفاقي پیش آيد‪ Return .‬بار ديگر‬ ‫نمايان نمي شود اما شما در پايان هر خط به ‌آن نیاز داريد‪ .‬فرمان ديگری که بايد انجام دهید‪ ،‬عبارتست از ‪ who‬که اين فرمان هر فردی‬

‫را که در حال برقراری ارتباط است را معرفي مي‌کند ‪:‬‬

‫‪$ who‬‬ ‫‪rlm‬‬ ‫‪tty0 sep 26 11:17‬‬ ‫‪pjw‬‬ ‫‪tty4 sep 26 11:30‬‬ ‫‪gerard‬‬ ‫‪tty7 sep 26 10:27‬‬ ‫‪mark‬‬ ‫‪tty9 sep 26 07:59‬‬ ‫‪you‬‬ ‫‪ttya sep 26 12:20‬‬ ‫‪$‬‬ ‫اولین ستون نام کاربران است‪ ،‬دومین ستون نام سیستم برای ارتباط مورد استفاده است‪ )tty( ] .‬به معنای دور تحرير (‪ )tele type‬است‪،‬‬ ‫هم معني قديمي برای پايانه[‪ .‬مابقي نشان دهنده زماني است کاربر ارتباط برقرار کرده است‪ .‬ممکن است شما عمل زير را انجام دهید‪.‬‬

‫‪$ who am i‬‬ ‫‪you‬‬ ‫‪ttya sep 26 12:20‬‬ ‫‪$‬‬ ‫اگر شما نام فرمان را اشتباه تايپ کنید‪ ،‬و به سراغ يك فرماني که وجود ندارد برويد‪ ،‬ممکن است با خود بگوئید که هیچ فرماني که‬

‫تحت اين عنوانباشد‪ ،‬يافت نمي‌شود ‪:‬‬

‫‪$ whom‬‬ ‫‪Misspelled command name ....‬‬ ‫‪whom: not found‬‬ ‫‪.... so system didn`t know how to run it‬‬ ‫‪$‬‬ ‫البته اگر شما از روی بي دقتي ‪ ،‬نام فرمان اصلي را تايپ کرده باشید‪ ،‬آن برنامه اجراء خواهد شد‪ ،‬البته شايد با نتايجي مبهم‪.‬‬

‫رفتارهاي غير متداول پايانه ها‬ ‫بعضي اوقات پايانه شما ممکن است به طرز غیر متداولي عمل کند‪ ،‬برای مثال هر حرف ممکن است دو بار تايپ شود‪ ،‬يا ‪Return‬‬

‫ممکن است ‪ ،‬مکان نما را در ابتدای ستون خط بعدی قرار ندهد‪ .‬شما معمول ً مي‌توانید اين جريان را با خاموش و روشن نمودن پايانه‬

‫تثبیت کنید يا با خارج شدن از ارتباط و سپس برقراری در ارتباط مجدد‪ .‬يا مي توانید توصیف فرمان ‪( STTy‬تنظیم انتخابهای پايانه) که‬ ‫در بخش اول فهرست راهنما است‪ ،‬را مطالعه کنید‪ .‬به منظور کنترل ارتباطات از طريق مضخصه ‪ Tab‬در صورتي که پايانه شما دارای‬

‫‪ Tabs‬نباشد‪ ،‬فرمان را تايپ کنید‪.‬‬

‫‪$ stty – tabs‬‬ ‫و سیستم‬

‫‪ Tabs‬را به تعداد صحیحي ا ز ‪ spaces‬تبديل خواهد کرد‪ .‬اگر پايانه های شما دارای نقاط ‪ Tab‬قابل تنظیم کامپیوتری‬

‫باشند‪ ،‬فرمان ‪ Tabs‬آنها را به طرز صحیحي برای شما تنظیم خواهد کرد‪( .‬شما بايد در مورد تايپ پايانه ‪ Tabs $‬به دقت عمل کنید‪ ،‬تا‬

‫اين عمل انجام شود‪ ،‬توصیف فرامین ‪ Tabs‬در فهرست راهنما را مطالعه کنید)‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪6/322‬‬

‫خطا در فرايند تايپ‬ ‫اگر شما خطای تايپي داشته باشید و آن را قبل از اينکه کلید ‪ Return‬را فشار دهید‪ ،‬ببینید ‪ ،‬دو روش برای اصلح آن وجود دارد ‪:‬‬

‫علئم پاك کردن در همان زمان يا از بین بردن تمام سطر و تايپ مجدد آن‪ .‬اگر شما علمت از بین بردن سطر را تايپ کرده باشید (پیش‬

‫فرض علمت @ ) اين عمل باعث مي‌شود که تمام سطر حذف شود‪ ،‬درست مثل زماني که شما هرگز آن سطر را تايپ نکرده بايد و يا‬ ‫آن عمل (تايپ) را از سطر جديدی شروع کرده باشید‪:‬‬

‫@‪$ ddtae‬‬ ‫‪Completely botched;start over‬‬ ‫‪date‬‬ ‫‪on a new line‬‬ ‫‪Mon sep 26 12:23:39 EDT 1983‬‬ ‫‪$‬‬ ‫علمت ‪ sharp #‬باعث پاك کردن آخرين حرف ‪ /‬علمت تايپ شده مي‌شود‪ ،‬هر ‪ #‬تنها يك حرف را پاك مي‌کند‪ ،‬و به ابتدای سطر بر‬ ‫مي گردد (البته نه فراتر از آن سطر)‪ .‬بنابراين اگر شما اشتباهاً تايپ کنید‪ ،‬شما مي‌تونید آن را به همین ترتیب اصلح نمائید‪.‬‬

‫‪$ dd#atte##e‬‬ ‫‪Fx it as you go‬‬ ‫‪Mon sep 26 12:24:02 EDT 1983‬‬ ‫‪$‬‬ ‫پاك‌کنهای خاص و علئم از بین بردن سطر‪ ،‬سیستمهای بسیار وابسته هستند‪ .‬در بسیاری از سیستمها (از جمله سیستمي که ما از آن‬

‫استفاده مي‌کنیم) ‪ ،‬علمت پاك کن تغییر يافته است و تبديل به ‪( back space‬يا پسبرد) شده است‪ ،‬که در پايانه‌های ويدئو به خوبي‬ ‫عمل مي‌کند‪ .‬شما سريع ًا مي‌توانید متوجه شويد که کدام مورد سیستم شما قرار گرفته است ‪:‬‬

‫‪$ datee‬‬ ‫‪Try‬‬ ‫‪datee :not found‬‬ ‫‪It`s not‬‬ ‫‪$ datee#‬‬ ‫‪Try #‬‬ ‫‪Mon sep 26 12:26:08‬‬ ‫‪it is #‬‬ ‫‪$‬‬ ‫ما علمت ‪ backspace‬يا پسبرد را به صورت ‪ ‬چاپ کرده‌ايم ‪ ،‬بنابراين مي‌تونید آن را ببینید)‪ .‬انتخاب شايع ديگر عبارتست از ‪CTL-‬‬ ‫‪ C‬برای از بین بردن سطر‪ .‬ما از علمت ‪ sharp #‬به عنوان مشخصه پاك کن برای مابقي اين بخش استفاده مي‌کنیم‪ ،‬چرا که اين علمت‬

‫قابل رؤيت است‪ ،‬اما در صورتي که سیستم شما متفاوت باشد‪ ،‬تنظیمات پايانه‌ای را انجام دهید‪ .‬بعد ‪ ،‬در فرايند «اندازه‌گیری محیط» ما‬

‫به شما مي گوئیم که چگونه پاك کن و علمت از بین بردن سطر را برای آنچه که شما دوست داريد يك بار يا برای همیشه تنظیم کنید ‪.‬‬

‫برای چه چیزی شما بايد پاك کن يا علمت از بین بردن سطر را به عنوان بخضي از متن‪ ،‬وارد کنید؟ اگر شما ‪ #‬يا علمت @ را به‬ ‫وسیله ‪ back slash‬جلوتر قرار دهید‪ ،‬اين امر باعث مي شودکه آن علمت معنای خاص خودش را از دست بدهد‪.‬‬ ‫بنابراين به منظور وارد کردن ‪ #‬يا @‬ ‫\ @ يا \ @‬

‫را تايپ کنید‪ .‬سیستم ممکن است مکان نمای پايانه را به سطر بعدی بعد از @ شما جلو ببرد‪ ،‬حتي اگر آن توسط ‪ backslash‬جلوتر‬ ‫واقع شده باشد‪ .‬در صورتي که علمت @ ثبت شود‪ ،‬نگران نباشید‪ Backslash .‬بعضي اوقات علمت ‪ escape‬نامیده مي‌شود‪ ،‬که به‬


‫محیط برنامه سازی لینوکس‬

‫‪7/322‬‬

‫میزان وسیع برای نشان دادن اين مطلب که علئم زير به طريقي خاص و ويژه هستند‪ ،‬مورد استفاده قرار مي‌گیرد‪ .‬به منظور پاك کردن‬ ‫‪ backslash‬شما بايد دو علمت پاك‌کن را تايپ کنید‪ .‬يعني ‪#‬‬

‫\ ‪ #‬آيا مي‌دانید چرا؟ علئمي که شما تايپ کرديد مورد بررسي قرار‬

‫گرفته و بوسیله توالي برنامه‌ها قبل از اينکه آنها به مقصدشان برسند‪ ،‬تعبیر و تفسیر مي شوند‪.‬‬

‫و اينکه آنها دقیقا ً چگونه تعبیر و تفسیر مي‌شوند نه تنها به جايي که پايان مي پذيرند بستگي ندارد بلکه به چگونگي رسیدن به آن‬

‫مرحله نیز بستگي ندارد‪ .‬هر علمتي را که تايپ مي‌کنید‪ ،‬بلفاصله در قسمت پايانه انعکاس پیدا مي‌کند مگر اينکه روند انعکاس‌يابي‬

‫پايان پذيرد (پايانه خاموش شود) که اين شرايط بسیار نادر است‪ .‬زمانیکه ‪ Return‬را فشار دهید علمتها به صورت موقتي توسط هسته‬

‫اصلي (‪ )kernel‬کنترل مي‌شوند‪ ،‬در نتیجه غلطها تايپي مي‌توانند با پاك کن و مشخصه از بین برنده سطرها‪ ،‬تصحیح شوند‪ .‬زماني که‬

‫پاك کن يا علمت از بین برنده سطر توسط ‪ backslash‬تقدم يابد‪ ،‬هسته اصلي (‪ )kernel‬باعث مي‌شود که ‪ backslash‬کنار زده شده‬ ‫و بقیه علمتها را بدون تعبیر و تفسیر کنترل کند‪ .‬زمانیکه ‪ Return‬را فشار دهید‪ ،‬علئم حفظ شده به برنامه ای فرستاده مي شوند که از‬

‫پايان خوانده مي‌شود‪ .‬آن برنامه نیز به نوبه خود ممکن است علئم و مشخصه‌ها را به روشهای خاصي تعبیر و تفسیر کند‪ ،‬برای مثال‪:‬‬

‫برنامه ‪ shell‬هرگونه تعبیر خاصي از علئم را در صورتي که توسط ‪ backslash‬تقدم يافته باشد را از بین مي‌برد‪ .‬در مورد اين موضوع‬

‫در فصل ‪ 3‬بحث خواهیم کرد‪ .‬اکنون‪ ،‬بايد به خاطر داشته باشید که ‪( kernel‬هسته اصلي) پاك‌کن و علمت از بین برنده سطرها را‬

‫پردازش مي‌کند و ‪ backslash‬تنها در صورتیکه پاك کن و علمت از بین برنده سطر را در تقدم قرار داده باشد‪ ،‬هر علمتي را که بعد از‬

‫آن رها شده باشد را به وسیله برنامه‌های ديگری به خوبي تعبیر و تفسیر مي کند‪.‬‬

‫تمرين ‪ 1‬ـ ‪ .1‬توضیح دهید در صورتي که ‪$‬‬

‫‪ @ \ date‬چه اتفاقي مي‌افتد‪.‬‬

‫تمرين ‪ 2‬ـ ‪ .1‬اغلب برنامه‌های ‪( shell‬اگر چه ‪ shell‬چاپ هفتم شامل آن نمي شود) علمت ‪ #‬را به عنوان معرفي به موضوع تعبیر‬

‫مي‌کنند‪ ،‬و تمام متن را از علمت ‪ #‬تا پايان سطر ناديده مي‌گیرند‪ .‬با توجه به اين موضوع‪ ،‬نسخه زير را توضیح دهید‪ ،‬فرض کنید که‬ ‫علمت پاك‌کن نیز به صورت ‪ #‬است ‪:‬‬

‫‪1983‬‬ ‫‪EDT 1983‬‬

‫‪$‬‬ ‫‪date‬‬ ‫‪Mon‬‬ ‫‪sep 12 : 39 : 56 EDT‬‬ ‫‪$‬‬ ‫‪# date‬‬ ‫‪Mon sep 26‬‬ ‫‪12 : 24: 21‬‬ ‫‪$ \ # date‬‬ ‫‪$ \ \ # date‬‬ ‫(يافت نشد) ‪# date : not found‬‬ ‫‪$‬‬

‫جلوتر تايپ كردن‬ ‫هسته اصلي (‪ )kernel‬آنچه را که شما تايپ مي کنید را همزمان با تايپ آن مي خواند‪ ،‬حتي اگر هسته اصلي مشغول کار ديگری باشد‪،‬‬

‫بنابراين با سرعت مورد دلخواه مطلب مورد نظرتان را تايپ کنید‪ ،‬و يا حتي هر زمان که مي‌خواهید‪ ،‬حتي زماني که برخي از فرمانها به‬

‫نفع شما چاپ نشوند‪ .‬در صورتیکه هنگام عمل چاپ سیستم ‪ ،‬شما تايپ انجام دهید‪ ،‬علئم ورودی شما در ترکیب با علئم خروجي به‬

‫نظر مي‌رسند اما‪ ،‬آنها ذخیره شده و به ترتیب صحیح تفسیر مي شوند‪ .‬مي‌توانید فرامین را يکي پس از ديگری بدون انتظار کشیدن برای‬

‫اتمام آنها يا حتي شروع آنها ‪ ،‬تايپ کنید‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪8/322‬‬

‫توقف برنامه‬ ‫شما مي‌توانید اغلب فرامین را با تايپ علمت ‪ delete‬متوقف سازيد‪ .‬کلید ‪ Break‬که در اغلب پايانه‌ها يافت مي‌شوند نیز مي‌تواند اين‬ ‫کار را انجام دهد‪ ،‬اگر چه اين عمل به سیستم بستگي دارد‪ .‬در چندين برنامه همچون برنامه ويراستاری متن‪ ،‬کلید ‪ delete‬هر آنچه را که‬ ‫برنامه انجام داده است را متوقف مي‌سازد اما شما را در آن برنامه رها مي‌کند‪ .‬خاموش کردن پايانه يا برداشتن تلفن‪ ،‬اغلب برنامه‌ها را‬

‫متوقف مي‌سازد‪ .‬اگر شما تنها بخواهید از حالت توقف بیرون آئید‪ ،‬برای مثال ‪ :‬برای حفظ برخي از مسائل ضروری از ناپديد شدن در‬

‫صفحه نمايش‪ ،‬فرمان ‪ CTL-S‬را تايپ کنید‪ .‬فرايند بازدهي تقريبا ً سريع متوقف مي شود‪ ،‬بدين ترتیب برنامه شما موقتاً تا زمانیکه شما‬ ‫دوباره آن را شروع کنید‪ ،‬متوقف مي‌شود‪ .‬زمانیکه شما بخواهید دوباره برنامه را ادامه دهید‪ ،‬فرمان ‪ CTL-q‬را تايپ کنید‪.‬‬

‫قطع كردن ارتباط‬ ‫ار دادن ‪ delete‬خارج شويد‪ .‬توجه کنید که خطاهای تايپي شما بر روی پايانه مری ظاهر نمي شود‪ .‬اگر شما در نظر داريد که به فردی‬

‫که در ارتباط نیست نامه بنويید يا به فردی که نمي خواهد با کراه مناسب برای قطع کردن ارتباط عبارتست از تايپ فرمان ‪ CTL-d‬به‬ ‫جای فرمان وجود ندارد‪ .‬به منظور پاسخ دهي ‪ ،‬فرمان ‪ write Mary $‬را تايپ کنید‪ .‬اين عمل مسیر ارتباطي دو طرفه‌ايي را بوجود‬ ‫مي‌آورد‪ .‬اکنون سطرهايي را که مری بر روی پايانه خودش تايپ کرده بر روی پايانه شما نیز تايپ مي‌شود و بر عکس‪ ،‬اگر چه اين‬ ‫مسیر آرام و آهسته عمل مي‌کند اما تا حدی بیه به ‪ talking to the moon‬است‪ .‬اگر در اواسط کاری قرار داريد‪ ،‬شما مجبوريد در‬

‫شرايطي قرار گیريد که بتوانید فرماني را تايپ کنید‪ .‬طبیعتاً هر برنامه ايي که شما در حال اجرای آن هستید بايد متوقف شود اما برخي از‬

‫برنامه‌ها همچون ويراستار ياـ ‪ write‬به خودی خود‪ ،‬دارای فرمانـ ( ! ) هستند که اين فرمان به طور موقتي از برنامهـ ‪ shell‬خارج‬

‫مي‌شود‪ ،‬جدول ‪ 2‬را در قسمت ضمیمه ‪ 1‬مورد مطالعه قرار دهید‪ .‬فرمان ‪ write‬هیچ قانوني را وضع نمي کند‪ ،‬بنابراين برای حفظ آنچه‬

‫تايپ مي‌کنیم و جلوگیری از مخدوش شدن با آنچه که مری تايپ مي‌کند‪ ،‬دستورالعملي لزم است ‪ .‬يك قانون اين است که چرخشي‬ ‫کرده و هر چرخش را با (‪ ) 0‬پايان دهد که اين علمت برای کلمه (‪ )over‬در نظر گرفته شده و برای مشخص نمودن هدفتان ‪ ،‬با‬

‫علمت (‪ ،)00‬آن را متوقف سازيد و از آن خارج شويد‪ ،‬اين علمت برای ‪ out‬و ‪ over‬در نظر گرفته شده است‪.‬‬

‫‪$ Eof‬‬ ‫‪$‬‬ ‫همچنین مي‌توانید از ‪ write‬با فشار دادن ‪ delete‬خارج شويد‪ .‬توجه کنید که خطاهای تايپي شما بر روی پايانه مری ظاهر نمي شود‪.‬‬

‫اگر شما در نظر داريد که به فردی که در ارتباط نیست نامه بنويید يا به فردی که نمي خواهد با کراه مناسب برای قطع کردن ارتباط‬

‫عبارتست از تايپ فرمان ‪ CTL-d‬به جای فرمان وجود ندارد‪ .‬به منظور پاسخ دهي ‪ ،‬فرمان ‪ write Mary $‬را تايپ کنید‪ .‬اين عمل‬ ‫مسیر ارتباطي دو طرفه‌ايي را بوجود مي‌آورد‪ .‬اکنون سطرهايي را که مری بر روی پايانه خودش تايپ کرده بر روی پايانه شما نیز تايپ‬

‫مي‌شود و بر عکس‪ ،‬اگر چه اين مسیر آرام و آهسته عمل مي‌کند اما تا حدی بیه به ‪ talking to the moon‬است‪ .‬اگر در اواسط کاری‬

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

‫از برنامه ‪ shell‬خارج مي‌شود‪ ،‬جدول ‪ 2‬را در قسمت ضمیمه ‪ 1‬مورد مطالعه قرار دهید‪ .‬فرمان ‪ write‬هیچ قانوني را وضع نمي کند‪،‬‬


‫محیط برنامه سازی لینوکس‬

‫‪9/322‬‬

‫بنابراين برای حفظ آنچه تايپ مي‌کنیم و جلوگیری از مخدوش شدن با آنچه که مری تايپ مي‌کند‪ ،‬دستورالعملي لزم است ‪ .‬يك قانون‬

‫اين است که چرخشي کرده و هر چرخش را با (‪ ) 0‬پايان دهد که اين علمت برای کلمه (‪ )over‬در نظر گرفته شده و برای مشخص‬ ‫نمودن هدفتان ‪ ،‬با علمت (‪ ،)00‬آن را متوقف سازيد و از آن خارج شويد‪ ،‬اين علمت برای ‪ out‬و ‪ over‬در نظر گرفته شده است‪.‬‬

‫سي ارتباط داشته باشد‪ ،‬در اين صوسي ارتباط داشته باشد‪ ،‬در اين صورت بايد به شما بگويد‪ .‬در صورتیکه هدف مورد نظر ارتباط‬ ‫برقرار کرده باشد اما پس از يك وقفه مناسب پاسخ ندهد‪ ،‬در اين صورت اين فرد ممکن است مشغول کاری بوده و يا از پايانه دور بوده‬ ‫باشد‪ ،‬در اين حالت ‪ CTl-d‬يا ‪ delete‬را تايپ کنید‪ .‬اگر مي‌خواهید فردی مزاحم شما نشود‪ ،‬از فرمان ‪ )mesg)1‬استفاده کنید‪.‬‬

‫اخبار‬ ‫بسیاری از سیستمهای يونیکس‪ ،‬سرويسهای خبری دارند‪ ،‬و به اين ترتیب کاربران را پهلو به پهلوی وقايع جالب و نه چندان جالب‬

‫حفظ مي کنند‪ .‬فرمان ‪ news $‬را تايپ کنید‪ .‬همچنین شبکه وسیعي از سیستمهای يونیکس وجود دارد که از طريق خطوط تلفن در‬

‫تماس قرار مي‌گیرند‪ ،‬در مورد شبکه‌های خبری و ‪ useNet‬از يك کارشناس سؤال کنید‪.‬‬

‫فهرست راهنما‬ ‫راهنمای برنامه‌ساز يونیکس اغلب آنچه را که شما نیازمند دانستن پیرامون سیستم هستید را توصیف مي‌کند‪ .‬بخش ‪ ،1‬با فرامین ارتباط‬ ‫دارد يعني شامل فرامیني است که ما در اين بخش در مورد آنها بحث مي‌کنیم‪ .‬بخش ‪ ،2‬سیستم صوت را توصیف مي‌کند‪ ،‬موضوع فصل‬

‫‪ 7‬و بخش ‪ ، 6‬اطلعاتي پیرامون بازيها دارد‪ .‬ما بقي بخشها در مورد نقشهای استفاده از برنامه هایـ ‪ ، C‬فرمت فايل و حفظ سیستم‬

‫صحبت مي کند‪( .‬تعداد اين بخشها از سیستمي به سیستم ديگر فرق مي کند)‪.‬‬

‫فهرستهای جابه جا شده در ابتدای کتاب راهنما را فراموش نکنید‪ ،‬شما مي‌توانید سريعاً از آن گذشته و برای فرامیني که ممکن است به‬ ‫آنچه که شما مي‌خواهید انجام دهید مربوط باشد‪ ،‬مطالعه‌ای گذرا از آن انجام دهید‪ .‬همچنین مقدمه‌ای در مورد سیستم وجود دارد که‬

‫اطلعاتي در مورد چگونگي عملکرد آن ارائه مي دهد‪ .‬غالباً فهرست راهنما بر روی خط حفظ مي‌شود‪ ،‬بنابراين‪ ،‬شما مي‌توانید آن را از‬ ‫طريق پايانه خودتان مطالعه کنید‪ .‬اگر شما غرق در کاری شديد و نتوانستید فرد متخصصي را به کمك بگیريد‪ ،‬مي توانید صفحه‬ ‫فهرست راهنما را بر روی پايانه خودتان با فرمان ‪ man comman-name‬چاپ کنید‪.‬‬

‫بنابراين برای اطلع از اينکه فرمان چه کسي بوده است ‪ :‬فرمان‬

‫ديگری; و اين موضوع به ‪ shell‬مي‌گويد که ورودی مسیر ديگری موجود نمي‌باشد‪ (.‬اينکه چگونه اين عمل واقعاً صورت مي‌پذيرد در‬

‫فصل بعدی توضیح داده مي‌شود) معمول مي‌توانید پايانه را خاموش و يا گوشي تلفن را برداريد اما‪ ،‬اين که اين عمل واقعاً ارتباط شما‬

‫را قطع مي‌کند يا نه‪ ،‬به سیستم تان بستگي دارد‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪10/322‬‬

‫پست الكترونيك‬ ‫سیستم باعث مي‌شود تا سیستم پستي جهت برقراری با کار بر ديگری‪ ،‬فراهم شود‪ .‬بنابراين در صورتیکه روزی ارتباط برقرار شود شما‬ ‫و پیام زير را خواهید ديد‪:‬‬

‫«نامه داريد»‬

‫واين پیغام را قبل از اولین برقراری ارتباط خواهید ديد‪ .‬به منظور خواندن نامه‌تان فرمان ‪ mail$‬را تايپ کنید‪ .‬نامة شما چاپ خواهد‬

‫شد و پیامي که پديدار مي‌شود به عنوان اولین و جديدترين پیام است‪ .‬بعد از هر عنوان نامه صبر کنید تا شما آنچه را که مي‌خواهید در‬

‫مورد آن اجرا کنید را اعلم کنید‪ .‬دو جواب اصلي عبارتند از ‪ d‬که اين جواب پیغام را حذف کنید و ديگری ‪ Return‬که کاری انجام‬

‫نمي‌دهد ( بنابراين نامه باقي مي‌ماند تا هر زمان ديگری که خواستید نامه‌تان را بخوانید) جوابهای ديگر عبارتند از ‪ P‬که باعث مي‌شود‬

‫پیغام دوباره چاپ شود‪ ،‬نام فايل ‪ S‬که باعث مي‌شود نامه در فايلي که شما به آن نام داده‌ايد ذخیره شود و ‪ q‬که برای رد شدن از نامه‪،‬‬

‫طراحي شده است‪(‌ .‬در صورتیکه شما ندانید که يك فايل شامل چه چیزی است به فکر مکان خاصي باشید که بتوانید اطلعات را‬

‫تحت يك نام انتخابي ذخیره کنیدو آن را بعدا بازيابي کنید‪ .‬فايلها موضوع بخش ‪ 102‬بوده و در واقع بخش عظیمي از کتاب را به خود‬

‫اختصاص داده‌اند‪ .‬پست الکترونیکي يکي از آن برنامه‌هايي است که احتمال ً متفاوت از آنچه مي‌باشد که ما در اينجا توصیف مي‌کنیم ‪.‬‬

‫انواع بسیارزيادی از آنها وجود دارد‪ .‬جهت اطلع از جزئیات به کتاب راهنما مراجعه کنید‪ .‬فرستادن نامه به افراد کار ساده‌ای است‪.‬‬ ‫فرض کنید نامه به فردی با نام ارتباطي ‪ nico‬فرستاده مي‌شود‪ .‬راحت ترين وساده‌ترين روش عبارتست از‪:‬‬

‫اکنون در متن نامه هر تعداد سطری که مي‌خواهید تايپ کنید بعد از آخرين سطر نامه فرمان ‪ Gntrd-d‬را تايپ کنید‪.‬‬

‫‪$ mail nico‬‬

‫‪$Ctl – d‬‬ ‫‪ Ctl-d‬به معنای پايان نامه به وسیله فرمان ‪ mail‬است که بیان مي‌دارد هیچ ورودی ديگری موجود نمي‌باشد اگر شما در نیمة راه‬

‫نظرتان را مبني بر ترکیب نامه تغییر داديد‪ ،‬کلید ‪ delete‬را به جای ‪ ctl-d‬فشار دهید‪ .‬نامه‌ای که به صورت نیمه کاره شکل گرفته است‬

‫در فايلي که به نام ‪ dead.letter‬است به جای فرمان انتقال ( ‪ )Send‬ذخیره مي‌شود‪ .‬به عنوان تمرين‪‌،‬نامه‌ای را برای خودتان بفرستید‪،‬‬

‫سپس‪‌،‬علمت ‪ mail‬را جهت خواندن نامه تايپ کنید‪.‬‬

‫(اين عمل به آن اندازه‌ای که به نظر مي‌رسد گمراه کننده نیست‪ ،‬اين کار مکانیسم يادآوری مناسبي است)‌‪ .‬روشهای ديگری برای‬

‫فرستادن نامه وجود دارد شما مي‌توانید نامه‌ای را که از قبل آماده شده است را بفرستید‪ ،‬مي‌توانید نامه‌ای را به تعدادی از افراد مورد‬

‫نظرتان در يك زمان خاص بفرستید و ممکن است قادر باشید نامه‌ را به افرادی در سیستمهای ديگر بفرستید‪ .‬جهت اطلع از جزئیات‬

‫بیشتر نسخه فرمان ‪ mail‬را در بخش ‪ 1‬فهرست راهنمای برنامه‌ساز يونیکس مطالعه کنید‪ .‬از اينجا به بعد ما از مفهم (‪ mail )1‬به معنای‬

‫صفحاتي که ‪ mail‬را در بخش ‪ 1‬کتاب راهنما توصیف مي‌کنند‪ ،‬استفاده مي‌کنیم همچنین ممکن است سرويس تقويم نیز وجود داشته‬ ‫باشد ( بخش ‪ ،‬تقويم ‪ 1‬را مطالعه کنید) و ما در فصل ‪ 4‬به شما نشان خواهیم داد که نامه چگونه در صورتي که پیش از اين کاری بر‬

‫روی آن انجام نگرفته است‪ ،‬تنظیم مي‌شود‪.‬‬

‫نوشتن نامه به كاربر ديگري‬ ‫از سیستم يونیکس شما دارای چندين کاربر است‪ .‬روزی‪ ،‬ناگهان‌‪.‬پايانه شما پیغامي شبیه به اين موضوع چاپ خواهد کرد‪:‬‬


‫محیط برنامه سازی لینوکس‬

‫‪11/322‬‬

‫‪message from mary tty 7‬‬

‫که اين پیغام با صدای بوق قابل توجهي همراه است‪ .‬مری مي‌خواهد که به شما نامه‌ا‌ی بنويسید‪ ،‬اما در صورتي که شما عمل واضحي‬

‫انجام ندهید‪ ،‬امکان اينکه شما قادر به پاسخ دهي باشید‪ man who $ ،‬را تايپ کنید و البته‪ man man $ ،‬در مورد فرمان فرد مورد نظر‬

‫اطلعاتي مي‌دهد‪.‬‬

‫دستورالعمل‌های کمك کننده به کامپیوتر‬

‫سیستم شما ممکن است دارای فرماني باشد که ‪ Learn‬نام داد که اين فرمان دستورالعمل‌ةای کمك دهنده به کامپیوتر را بر روی فايل‬ ‫سیستم و فايلهای اصلي ويراستار‪ ،‬آماده سازی اسناد و حتي برنامه ‪ C‬فراهم مي‌آورد‪.‬‬

‫فرمان ‪ learn $‬را تايپ کنید‪ .‬اگر فرمان ‪ Learn‬در سیستم شما باشد‪ ،‬در اين صورت آنچه را که شما بايد از آنجا انجام دهید را به شما‬

‫اعلم مي‌کند‪ .‬در صورتي که اين فرمان اجرا نشود در مورد فرمان ‪ teach‬اقدام کنید‪.‬‬

‫بازيها‬ ‫بازيها همیشه پذيرفته شده نیستند امايکي از بهترين راهها برای کسب آسايش و راحتي از کامپیوترها و پايانه‌ها ‪ ،‬اجرای بازيها است‪.‬‬

‫سیستم يونیکس با تجهیزات معمولي از بازيها همراه است و غالبا ً اين تجهیزات به صورت محلي ضمیمه مي‌شوند‪ .‬اطراف را مورد‬ ‫بررسي قرارداده يا بخش ‪ 6‬فهرست راهنما را مورد مطالعه قرار دهید‪.‬‬

‫‪2‬ـ ‪ ) 1‬استفاده روز به روز ‪ :‬فايلها و فرامين معمول‬ ‫اطلعات در سیستم يونیکس در فايلها ذخیره مي‌شود‪ ،‬که بیشتر شبیه به فايلهای اداری معمولي هستند‪ .‬هر فايل دارای نام‪ ،‬محتوا و‬ ‫مکاني برای حفظ آن است و برخي از اطلعات اداری ( اجرايي) همچون فردی که مالك آن است و میزان بزرگي آن‪ ،‬مي‌باشد فايل‬ ‫ممکن است دارای نامه يا لیستي از نامها و آدرسها باشد يا منبع اطلعات برنامه‌ها يا اطلعاتي که بايد به به وسیله برنامه استفاده شود يا‬

‫حتي دارای برنامه ها به شکل قابل توجیه و ديگر موضوعات غیر متني باشد‪ .‬فايل سیستم يونیکس به صورت سازمان يافته است‪.‬‬

‫بنابراين شما مي‌توانید فايلهای شخصي خودتان را بدون مداخلت با فايلهای متعلق به افراد ديگر حفظ کنید و افراد را از دخالت پیدا‬

‫کردن در مورد فايلهای خودتان منع نمائید‪ .‬تعداد زيادی برنامه وجود دارد که فايلها را کنترل مي‌کند‪ .‬اما اکنون ما تنها به اکثر آنهايي که‬

‫به طور مکرر توسط افراد مورد استفاده قرار مي‌گیرد‪ ،‬سرورکار داريم‪ .‬فصل ‪ 2‬شامل بحث سیستماتیکي در مورد فايل سیستم است و‬ ‫بسیاری از ديگر فرامین مربوط به فايلها را معرفي مي‌کند‪.‬‬

‫ايجاد فايل ـ فايل ويراستار‬

‫در صورتي که بخواهید برگه يا نامه و يا يك برنامه را تايپ نمائید‪ .‬چگونه اطلعات ذخیره شده در ماشینـ ( سیستم) را بدست‬

‫مي‌آوريد؟‬

‫اغلب اين کارها با فايل ويراستار متن که برنامه‌‌ای برای ذخیره کردن و کنترل اطلعات در کامپیوتر است انجام مي‌گیرد‪ ،‬تقريبا ً هر‬

‫سیستم يونیکس دارای ويراستار صفحه نمايش است ويراستاری که مزيتهايي را از پايانه‌های مدرن گرفته وبدين وسیله تأثیرات تغییرات‬ ‫ويراستاری شما را در متن همزمان با بوجود آوردن متن‪ ،‬نشان مي‌دهد‪ .‬دو نمونه از مشهورترين اين فايلها عبارتند از ‪ emacs,vi‬ما در‬


‫محیط برنامه سازی لینوکس‬

‫‪12/322‬‬

‫نظر نداريم که هیچ نوع ويراستار صفحه نمايش خاصي را در اينجا تشريح کنیم‪ ،‬و اين امر تا حدی به دلیل محدوديتهای حروف چیني‬

‫و تا حدی به دلیل عدم وود نوعي استاندارد است‪ .‬با اين وجود يك نمونه ويراستار قديمي‌تر که ‪ ed‬نامیده مي‌شود وجود دارد که‬

‫مطمئنا ً برروی سیستم شما موجود است‪ .‬اين نوع ويراستار هیچ گونه مزيتي از خصوصیات پايانه‌های دريافت نکرده است‪ ،‬بنابراين بر‬

‫روی هر گونه پايانه‌ای کار خواهد کرد‪ .‬اين فايل همچنین اصولي از ديگر برنامه‌های ضروری را تشکیل مي‌دهد( شامل برخي از‬

‫ويراستارهای صفحه نمايش ) بنابراين فايل ارزش يادگیری را دارد‪ .‬ضمیمه ‪ 1‬شامل نسخة مختصری از اين فايل است‪ .‬اين که شما چه‬

‫نوع ويراستاری را ترجیح مي‌دهید مهم نیست‪ ،‬بلکه مهم است که شما آن را به خوبي فرا گرفته تا بتوانید فايلهايي را ايجاد نمائید‪ .‬در‬

‫اينجا ما از فايل ‪ ed‬جهت ارائه بحث استفاده مي‌کنیم و مطمئن هستیم که شما مي‌توانید مثالهای ما را بر روی سیستم‌تان اجرا نمائید اما‬

‫حتما ً از ويراستاری که بهتر دوست داريد استفاده نمائید‪ .‬به منظور استفاده از ‪ ed‬جهت ايجاد فايلي که ‪ junk‬نامیده مي‌شود ( به همراه‬ ‫متوني در آن ) کارهای زير را انجام دهید‪:‬‬

‫فرمان ‪ ed‬ويراستار متن را به منظور‬

‫‪$‬‬

‫‪ed‬‬

‫افزودن متن به کمك بطلبید ‪a‬‬

‫اكنون در هر متني كه مي‌خواهيد‬ ‫تايپ کنید‪.‬‬

‫•‬

‫به وسيله خودش ’‬

‫‪.‬‬

‫‘ را به منظور متوقف نمودن‬

‫افزايش متن‪،‬تايپ کنید‪ .‬متن تان را در فايلي که‬

‫تحت عنوان ‪ junk‬است‪‌،‬بنويسید‪q .‬‬

‫تعدادی از علئم نوشته شده را چاپ مي‌کند‪.‬‬

‫‪w junk‬‬ ‫‪39‬‬ ‫‪ed‬‬ ‫‪$‬‬

‫از ‪ ed‬خارج شويد‪.‬‬

‫فرمان ‪ ’’( a‬ضمیمه سازی ‘‘( به ‪ ed‬مي‌گويد شروع به جمع‌آوری متن کند‪.‬‬ ‫’’ ‪.‬‬

‫‘‘ که نشان دهنة پايان متن است بايد در شروع خط ( سطر) به وسیله خودش تايپ شود‪ .‬آن را تازمانیکه تايپ‬

‫شود فراموش نکنید‪ .‬ديگر فرامین ‪ ed‬نبايد سازماندهي شوند هر چیزی که شما تايپ مي‌کنید مادامي که متن افزوده‬

‫مي‌شود مورد بررسي و کنترل قرار خواهد گرفت ) فرمان ويراستاری ‪”( w‬نوشتن“) اطلعاتي را که شما تايپ مي‌کنید‬ ‫را ذخیره مي‌کند’’ ‪ “ w junk‬آن را در فايلي که ‪ junk‬نامیده مي‌شود و ما ‪ junk‬را از اين رو انتخاب کرده‌ايم تا پیشنهاد‬

‫کنیم که اين فايل خیلي مهم نیست‪ Ed .‬با تعدادی از علئمي که آن را در فايل قرار مي‌دهد پاسخ مي‌دهد‪ .‬تا زمانیکه‬ ‫‪ w‬فرمان ندهد‪ ،‬هیچ چیزی به صورت دائمي ذخیره نمي‌شود بنابراين اگر شما گوش را گذاشته ‌ و به خانه برويد‪،‬‬

‫اطلعات در فايل ذخیره شده است‪ ( .‬اگر شما گوشي را مادامي که در حال ويرايش هست بگذاريد‪ ،‬اطلعاتي که‬ ‫درحال پردازش است‪ ،‬در فايلي که ‪ ed.hup‬نامیده مي‌شود ذخیره مي‌شود که بدين ترتیب شما مي‌توانید به فعالیت‬ ‫متني خودتان ادامه دهید‪ ).‬اگر سیستم دچار سروصدا شد( برای مثال به صورت غیرمنتظره و به دلي اشکالت سخت‬

‫افزاری و نرم افزاری بايستید) البته زمانیکه شما در حال ويراستاری هستید‪ ،‬فايل شما تنها دارای آنچیزی است که‬


‫محیط برنامه سازی لینوکس‬

‫‪13/322‬‬

‫آخرين فرمان نوشتاری آنجا قرار داده است‪ .‬اما پس از اينکه ‪ ( w‬نوشتن) اطلعات به صورت دائمي ثبت شد‪ ،‬شما‬

‫مي‌توانید بعداً با تايپ فرمان ‪ ed junk $‬دوباره به آنها دسترسي پیدا کنید البته مي‌توانید متني را که شما تايپ کرده‌ايد‬

‫را ويراستاری کنید و يا خطاهای امليي آن را تصحیح نمائید‪ .‬کلمات را تغییر دهید‪ ،‬پاراگرافها را دوباره مرتب کنید‬

‫و کارهايي از اين قبیل‪ ،‬زماني که شما اين کارها را نجام داديد‪‌،‬فرمان ‪ ( q‬خروج) اعلم مي‌دارد که از فايل ويراستاری‬ ‫خارج شويد‪.‬‬

‫چه فايلهايي خارج از برنامه هستند؟‬

‫اجازه دهید دو فايل ايجاد کنیم فايل ‪ Temp , junk‬بنابراين ما آنچه را که داريم مي‌شناسیم‪.‬‬

‫‪$ ed‬‬ ‫‪a‬‬ ‫باشد يا نباشد‬ ‫•‬

‫‪W junk‬‬ ‫‪19‬‬ ‫‪q‬‬ ‫‪$ ed‬‬ ‫‪A‬‬ ‫سوالي مطرح است‬ ‫•‬

‫‪w Temp‬‬ ‫‪22‬‬ ‫‪q‬‬ ‫‪$‬‬ ‫علمتي که از ‪ ed‬منظور مي‌شود عبارتست از علمتي در پايان هر خط (سطر) و که خط جديد يا سطر جديد نامیده مي‌شود اين علمت‬ ‫چگونگي نشان دادن ‪ Return‬سیستم را نشان مي‌دهد‪ .‬فرمان ‪ ( 1s‬نه محتوا) از فايلها را فهرست مي‌کند‪:‬‬

‫‪$ 1s‬‬ ‫‪junk‬‬ ‫‪Temp‬‬ ‫‪$‬‬ ‫که اين نامها ‪ ،‬دوفايلي هستند که تنها ايجاد شده‌اند( ممکن است فايلهای ديگری نیزوجود داشته باشند که شما ايجاد نکرده باشید) نامها‬

‫به ترتیب حروف الفبايي به صورت اتوماتیك طبقه بندی مي‌شوند ‌‪ 1s .‬شبیه اغلب فرامین‪ ،‬دارای انتخابهايي است که ممکن است برای‬ ‫تغییر رفتارهای غلط به کار برده شوند‪ .‬انتخابها نام فرامین را در سطر فرمانها پي گیری مي‌کنند و معمول از علمت تفريق’ ــ ‘ و از يك‬

‫حرف تنها که معمولً دارای معنا است‪ ،‬تشکیل شده است‪ .‬برای مثال‪ 1s-t ،‬باعث مي‌شود که فايلها به ترتیب زماني فهرست شوند‪:‬‬ ‫ترتیبي که در آن آنهايي که آخر تغییر يافته‌اند غالب ًا جديدتر بوده و در اولويت آخر هستند‪.‬‬

‫انتخاب ‪ 1‬ـ فهرست طويلي را نشان مي‌دهد که اطلعات زيادی در مورد هر فايل فراهم مي‌آورد‪.‬‬

‫‪$ 1s-t‬‬ ‫‪Temp‬‬ ‫‪Junk‬‬ ‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪14/322‬‬

‫‪$ 1s-1‬‬ ‫‪Total 2‬‬ ‫ ‪- rw-r- - r-‬‬‫‪1 jou‬‬ ‫‪19 sep 26 16:25 junk‬‬ ‫ ‪- rw - r - - r -‬‬‫‪22 sep 26 16:26 Temp‬‬ ‫ ‪- rw-r - - r -‬‬‫" ‪ " total 2‬نشان مي‌دهد که چه تعداد از بلوکهای فضای ديسك در يك فايل اشغال شده است و يك بلوك معمول ً شامل ‪ 512‬يا‬ ‫‪ 1024‬کاراکتر است‪.‬‬

‫رديف ‪ - - rw r - - r -‬نشان مي‌دهد که چه کسي اجازه خواندن و نوشتن در يك فايل را دارد‪ .‬در اين مورد مالك اصلي ( شما )‬

‫مي‌توانید بخوانید و بنويسید‪ ،‬اما ديگران تنها مي‌توانند آن فايل را بخوانند عدد ‪ " "1‬که به دنبال آن مي‌آيد نشان دهنده تعداد ارتباط به‬

‫فايل است از اين موضوع تا رسیدن به فصل ‪ 2‬صرفنظر کنید‪ " .‬شما " مالك فايل هستید‪ ،‬يعني ‪ ،‬فردی که آن فايل را ايجاد کرده‬

‫است‪ 22 .‬و ‪ 19‬تعداد کاراکترهايي است که با فايلها در مکاتبه بودند‪ .‬که اين تعداد با تعدادی که شما از فايل ‪ ed‬دريافت کرده‌ايد‪،‬‬

‫هماهنگي دارد‪ .‬تاريخ وزمان نشان مي‌دهد که چه زماني فايل آخرين تغییر را پیدا کرده است انتخابها مي‌تواند گروه‌بندی شود‪1s, 1t :‬‬

‫داده‌هايي همانند ‪ 1s-1‬را ارائه مي‌دهد اما بر اساس آخرين فايلها طبقه بندی مي‌شود‪ .‬انتخاب –‪ u‬اطلعاتي را در مورد زمان خاصي که‬

‫فايل مورد استفاده قرار گرفته است ارائه مي‌دهد‪:‬‬

‫‪ 1s - 1ut‬لیست طولي (‪ )1-‬را به ترتیب آخرين استفاده نشان مي‌دهد‪ .‬انتخاب مورد ‪ r -‬ترتیب خروجي را بر عکس مي‌کند‪ .‬بنابراين‪،‬‬

‫‪ 1s-rt‬به ترتیب آخرين مورد استفاده شده فهرست مي‌شود‪ .‬همچنین شما مي‌توانید فايلها را به نامهايي که مورد علقه‌تان است‪ ،‬نام‬ ‫گذاری کنید و ‪ 1s‬تنها اطلعاتي در مورد خودشان را ‪ ،‬فهرست مي‌کنند‪:‬‬

‫‪$ 1s - 1 junk‬‬ ‫‪- rw -r - - r - - 1jou‬‬ ‫‪19 sep 26 16:25 junk‬‬ ‫‪$‬‬ ‫رديف يا رشته‌هايي که برنامه‌ها را ادامه مي‌دهند بر اساس سطر فرمان نام گذاری مي‌شوند‪ ،‬مثل ‪ junk , -1‬در نمونه بال‪‌،‬اين موارد‬

‫تحت عنوان «شناسنامه برنامه » نام گذاری و شناخته مي‌شوند‪ .‬شناسه‌ها معمول ً شامل انتخابها يا نامهای فايلهايي هستند که بوسیله‬ ‫فرمانها مورد استفاده قرار مي‌گیرند‪ .‬انتخابها را به وسیله علمت منها ‌(ـ ) و يك حرف تنها مشخص کنید مثل ‪ t -‬يا به صورت ترکیبي ‪-‬‬

‫‪ 1t‬که اين مورد بیشتر شايع است‪ .‬به طور کلي در صورتیکه يك فرمان پذيرفته شود‪ ،‬مثل شناسه انتخابي‪ ،‬آنها هر گونه شناسه نام فايلها‬

‫را در تقدم قرار مي‌دهند اما ممکن است در هر ترتیب ديگری جور ديگری به نظر برسد‪ .‬اما برنامه‌های يونیکس در کنترلشان پیرامون‬ ‫انتخابهای چندگانه‪‌،‬بي نظم هستند‪ .‬برای مثال هفتمین چاپ استاندارد ‪ 1s‬مورد زی را‬ ‫در چاپ هفتم فعال نمي باشد‬

‫‪$‬‬

‫‪1s - 1 -t‬‬

‫به عنوان معادلي برای ‪ 1s-1t‬نمي‌پذيرد‪ ،‬هر چند دنبال برنامه‌ها نیازمندند انتخابهای چند گانه جهت مجزا شدن مي باشند‪.‬‬

‫مادامي که اطلعات بیشتری فراگیريد‪ ،‬متوجه خواهید شد که نظم کم وجود داشته يا سیستم در حالت شناسه انتخابي قراردارد‪ .‬هر زمان‬ ‫دارای ويژگي ‌ منحصر به فرد خود و انتخاب ‌های مخصوص به خود در مورد آن خروجي که به معنای آن است مي‌باشد ( غالبا ً اين‬

‫موارد متفاوت از همان نقش در فرامین ديگر مي باشند) اين رفتارهای غیرقابل پیش بیني آزار دهنده بوده و غالبا ً به عنوان نقصان و‬

‫ضعف بزرگي در يك سیستم‪ .‬مطرح مي‌باشند‪ .‬اگر چه اين شرايط در حال بهبوديابي هستند ( انواع جديد غالب ًا دارای يکنواختي بیشتری‬ ‫مي‌باشد) و ما تمام آنچه که ما مي‌توانیم پیشنهاد کنیم اين است که شما تلش کنید تا زمانیکه که در برنامه شخصیتان چیزی مي‌نويسید‬

‫به بهترين نحو اين کار را انجام دهید و در اين میان يك کپي ازمهارتتان را حفظ کنید ‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪15/322‬‬

‫فايلهای چاپگر ـ ‪cat , pr‬‬

‫اكنون شما داراي برخي از فايلها هستيد‪ ،‬اكنون چگونه شما محتواي آنها را مورد بررسي‬ ‫قرار دهيد‪ ،‬برنامه‌هاي زيادي وجود دارد كه اين كار ر انجام مي‌دهد‪ ،‬كه احتمالً اين عمل‬ ‫بيشتر از مورد نياز است‪ .‬يكي از اين امكانات اين است كه از ويراستار استفاده كنيد‪:‬‬ ‫‪ ed‬به تعداد ‪ 19‬كاراكتر را در ‪ junk‬ثبت مي‌كند‬ ‫سطر ‪ 1‬تا آخر را چاپ مي‌کند‬ ‫و فايل تنها يك سطر دارد‬

‫تمام کارها انجام گرفته است‬

‫‪$‬‬

‫‪junk‬‬

‫‪ed‬‬

‫‪19‬‬ ‫‪p$ , 1‬‬

‫باشد يا نباشد‬

‫‪q‬‬ ‫‪$‬‬ ‫‪ ed‬با ثبت تعدادی از کاراکترها در ‪ junk‬شروع به کار مي‌کند فرمان ‪ p ، 1$‬اظهار دارد که آن تمام سطرها را در فايل چاپ کند‪ .‬پس از‬

‫اينکه فراگرفتید چگونه از ويراستار استفاده کنید‪ ،‬مي‌توانید به صورت انتخابي در موردبخشهايي که چاپ مي کنید‪ ،‬عمل کنید‪ ،‬زماني که‬

‫امکان استفاده از ويراستار برای چاپ وجود نداشته باشد موقعیتهايي وجود دارد‪ .‬برای مثال‪‌،‬در مورد میزان بزرگي فايل ‪ ed‬که بتواند‬ ‫مورد استفاده قرار گیرد‪‌،‬محدوديتهايي وجود دارد ( چندين هزار سطر) علوه بر اين‪ ،‬اين فايل تنها يك فايل را در يك زمان چاپ‬ ‫مي‌کند‪ ،‬و بعضي اوقات شما مي‌خواهید چندين فايل را چاپ کنید به صورتي که يکي پس از ديگری بوده و هیچ‌گونه توقفي در حین‬

‫چاپ وجود نداشته باشد‪ .‬بنابراين در اين زمینه مجموعه‌ای از راه‌حلها وجود دارد‪ .‬اولین مورد فايل ‪ cou‬است‪ ،‬که اين فايل از تمام‬

‫فرامین چاپ ساده‌تر است ‪ .‬اولین مورد فايل تمام فايلهايي که توسط شناسه‌هايشان نام گذاری شده‌اند را چاپ مي‌کنید ‪:‬‬

‫فايل نام گذاری شده يا فايلها در پايانه يکي پس از ديگری بدون وقفه و فاصله الحاق مي‌شوند‪،‬‬

‫‪$ cat junk‬‬ ‫‪To be or not to be‬‬ ‫‪$ cat Temp‬‬ ‫‪That is the question‬‬ ‫‪$ cat junk Temp‬‬ ‫‪To be or not to be‬‬ ‫‪That is the question‬‬ ‫‪$‬‬

‫( از اين رو نام «‪ »cat‬انتخاب شده است) در مورد فايلهای کوتاه مشکي وجود ندارد اما برای فايلهای بزرگ مشکل پیش مي‌آيد در‬

‫صورتي که شما با سرعت بسیار بال به کامپیوترتان متصل شويد‪ ،‬بايد سريع ًا ‪ Ctl-s‬را برای متوقف کردن خروج از ‪ Cat‬قبل از اينکه اين‬

‫برنامه ازصفحه نمايش شما خارج شود اجرا کنید هیچ فرمان استانداردی برای چاپ يك فايل بر روی پايانه ويدئويي که در يك زمان‬

‫دارای صفحه نمايش کامل است وجود ندارد‪ ،‬اگر چه تقريبا ً هر سیستم يونیکس دارای يك نمونه از اين فرمان مي‌باشد‪ .‬سیستم شما‬

‫ممکن است دارای فرمان ‪ make‬يا ‪ pg‬باشد سیستم ما دارای فرماني است که ‪ p‬نامیده مي شود‪ ،‬ما به شما اجراء آن را در فصل ‪ 6‬نشان‬ ‫خواهیم داد‪ .‬همچون ‪ cat‬فرمان ‪ pr‬محتوای تمام فايلهايي که در يك لیست‪‌،‬نام گذاری شده‌اند را چاپ مي‌کند اما به شکل مناسبي برای‬

‫چاپگرهای سطری‪ ،‬هر صفحه دارای ‪ 66‬سطر است ( ‪ 11‬اينچ) و نیز دارای تاريخ و زماني است که آن فايل تغییر يافته است‪ ،‬شماره‬

‫صفحه و نام فايل در بالی هرصفحه و تعدادی سطر اضافي به منظور رد کردن تاخوردگي در کاغذ از جمله ديگر امکانات اين فايل‬ ‫است‪ .‬بنابراين ‪ junk‬را به صورت مرتب چاپ کرده و سپس به بالی صفحه جديد رفته و ‪ Temp‬را به صورت مرتب چاپ کنید‪:‬‬

‫‪$ pr junk Temp‬‬


‫محیط برنامه سازی لینوکس‬

‫‪16/322‬‬

‫‪Junk page 1‬‬

‫‪ pr‬نیز مي‌تواند خروجیهای چند ستوني بوجود آورد‪:‬‬

‫‪Sep 26 16:25 1983‬‬ ‫‪To be or not To be‬‬

‫(‪)60 more blank lines‬‬ ‫‪Sep 26 16:26 1983 Temp page 1‬‬ ‫‪That is the question‬‬ ‫(‪)60 more blank lines‬‬ ‫‪$‬‬

‫‪$ pr- 3 filename‬‬ ‫هر فايل را در طرحهای سه ستوني چاپ کنید‪ .‬مي‌توانید هر تعداد مورد قبول را در محل " ‪ " 3‬به کار ببريد و ‪ pr‬اين کار را به بهترين‬

‫نحو انجام مي‌دهد‪ .‬کلمهـ ‪ filename‬مکان مشخصي برای لیست نامهای فايلها مي‌باشد) ‪ pr-m‬مجمومه‌ای از فايلها را در ستونهای‬

‫موازی چاپ مي‌کند‪pr)1( .‬را مورد مطالعه قرار دهید‪ .‬اين نکته بايد مورد توجه قرار گیرد که ‪ pr‬يك برنامه قالب‌بندی به معنای حقیقي‬

‫تنظیم سطرها و فاصله‌بندی حاشیه‌ها نمي‌باشد برنامه قالب‌بندی صحیح ‪ nroff‬و ‪ Troff‬است که در فصل ‪ 9‬مورد بحث قرار مي‌گیرد‪.‬‬

‫همچنین فرامیني وجود دارد که فايلها را با سرعت بالی چاپگر‪ ،‬چاپ مي‌کند‪ .‬به فهرست مورد نظرتان تحت نامهايي شبیه ‪pr , Lp 1‬‬

‫نگاه کنید يا " چاپگر" را در فهرست جابجا شده مورد جستجو قرار دهید‪ ،‬آنچیزی که بايد مورد استفاده قرار گیرد به تجهیزاتي بستگي‬

‫دارد که به ماشین شما ( سیستم) متصل است‪ pr .‬او ‪ pr‬غالباً به صورت توأم مورد استفاده قرار مي‌گیرد پس از اينکه ‪ pr‬اطلعات را به‬

‫صورت کامل فرمت کرد‪ pr 1 ،‬مکانیسم گرفتن آنها را از چاپگر خطي‪ ،‬کنترل مي‌کند‪.‬‬ ‫در مراحل بعدی به اين موضوع مي‌ پردازيم‪.‬‬

‫انتقال‪ ،‬كپي‪ ،‬پاك‪ ‬كردن‪ ‬فايلها‪mr,cp ,rm  ‬‬

‫اجازه دهيد به فرامين ديگري نيز بپردازيم‪ .‬اولين موضوع اين است كه نام فايل را عوض‬ ‫كنيم نام‌گذاري جديد يك فايل به وسيله " انتقال" آن از يك نام به نام ديگر انجام مي‌پذيرد‪ .‬مثل‬ ‫اين مورد‪:‬‬ ‫‪$‬‬

‫‪precious‬‬

‫‪junk‬‬

‫‪mv‬‬

‫اين مورد به اين معناست که فايلي که برای نامیدن ‪ junk‬به کار رفته است‪ ،‬اکنون تحت عنوان ‪ precious‬مي‌باشد و محتوای آنها تغییر‬ ‫نکرده است‪ .‬اگر شما ‪ 1S‬را اکنون اجراکنید‪ ،‬فهرست متفاوتي را خواهید ديد‪ junk :‬ديگر وجود ندارد اما ‪ precious‬موجود مي‌باشد‪.‬‬

‫‪$ 1s‬‬ ‫‪Precious‬‬ ‫‪Temp‬‬ ‫‪$ cat junk‬‬ ‫‪cat con,t open junk‬‬ ‫‪$‬‬ ‫آگاه باشید که اگر فايلي را به فايل ديگری که از قبل وجود داشته است انتقال دهید فايل مورد نظر‪ ،‬جايگزين مي‌شود‪ .‬به منظور گرفتن‬ ‫کپي از فايل ( يعني داشتن دو نسخه از چیزی) از فرمان ‪ cp‬استفاده کنید‪:‬‬

‫کپي دوتايي از ‪ percious‬از ‪ Percious.save‬تهیه کنید‪.‬‬

‫‪$ cp percious percious save‬‬

‫نهايتا ً زماني که ما از ايجاد و انتقال فايلها خسته شديد‪ ،‬فرمان ‪ ، rm‬تمام فايلهايي را که شما نام‌گاری کرده‌ايد را پاك مي‌کند ‪rm $ .‬‬


‫محیط برنامه سازی لینوکس‬

‫‪17/322‬‬

‫‪Temp junk‬‬

‫‪Rm:junk nenexistent‬‬ ‫‪$‬‬ ‫در صورتیکه يکي از فايلهايي که بايد پاك شود موجود نباشد‪ ،‬بايد اطلع داشته باشید اما ‪ rm‬مثل اغلب فرامین يونیکس اين کار را به‬ ‫آرامي انجام مي‌دهد‪ .‬هیچ دای ناموزوني در اين حین به گوش نمي‌رسد و پیغامهای خطا محدود بوده و بعضي اوقات سودند لغي باشند‪.‬‬

‫خلصه نويسي مي‌تواند برای افراد تازه وارد‪ ،‬دردسرساز باشد اما کاربران با تجربه فرامین طويل وپرحرف را آزار دهنده تلقي مي‌کنند‪.‬‬

‫درون نام يك فايل چه چیزی است؟‬ ‫تاکنون از نام فايلها بدون اينکه بگويیم يك نام قانوني چیست؟ استفاده کرده‌ايم‪ ،‬اکنون زمان مجموعه‌ای از قوانین است اول اينکه نامهای‬ ‫فايلها به ‪ 14‬کاراکتر محدود مي‌باشند‪ .‬دوم اينکه‪ ،‬اگر چه مي‌توانید تقريباً از هر کاراکتری در نام‌گذاری فايل استفاده کنید اما عقل سلیم‬

‫مي‌گويد شما بايد به کاراکترهايي متوجه شويد که مشهود هستند و از کاراکترهايي که ممکن است به ديگر معناها به کار روند‪،‬‬

‫بپرهیزيد‪ .‬برای مثال‪ ،‬پیش از اين ديديم که در فرمان ‪ 1s-t , 1 s‬به معنای فهرست فايلها به ترتیب زماني است‪ .‬بنابراين اگر شما فايلي‬

‫داريد که نام آن ‪ t -‬باشد در نتیجه برای فهرست آن بر اساس نام وقت زيادی بايد صرف کنید‪ ( .‬چگونه بايد اين کار را انجام دهید)‬

‫علوه بر علمت منها(ـ ) به عنوان اولین کاراکتر‪ ،‬کاراکترهای ديگری با معنای خاص وجود دارد ‪ .‬به منظور اجتناب از ايجاد مشکل‪ ،‬بايد‬

‫در استفاده از حروف تنها ‪ ،‬اعداد‪ ،‬دوره و زير خط دار کردن تا زمانیکه با موقعیت آشنايي پیدا کنید‪ ،‬به خوبي و با احتیاط عمل کنید (‬

‫دوره و زير خط دار کردن ‪ )under score‬به صورت قراردادی به منظور تقسیم نام فايلها به بخشهايي همچون ‪ Precious. Save‬مورد‬

‫استفاده قرار مي‌گیرد) نهايتا ً فراموش نکنید که هر مورد‪ ،‬موضوع مجزايي به شمار مي‌رود‪ ،‬برای مثال ‪ Junk , Junk, junk‬هر کدام سه‬ ‫نام متفاوت مي‌باشد‪.‬‬

‫تعدادي از فرامين مفيد‬ ‫اکنون که شما از اصول ايجاد فايل‪ ،‬فهرست نامهای آنها و چاپ محتويات آنها اطلع پیدا کرديد‪‌،‬مي‌توانیم شش مورد از فرامین پردازش‬

‫فايلها را مورد بررسي قرار دهیم‪ .‬به منظور اينکه بحث جدی داشته باشیم ‪ .‬از فايلي استفاده خواهیم کرد که (شعر) ‪ poem‬نام دارد و‬ ‫حاوی شعر مشهوری از ‪ Augustus de morgan‬است‪.‬‬

‫اجازه دهید اين فايل را با ‪ ed‬ايجاد کنیم‪.‬‬

‫‪$ ed‬‬ ‫‪a‬‬ ‫‪Great fleas have little fleas‬‬ ‫‪Upon their back to bite em,‬‬ ‫‪And little fleas have lesser fleas,‬‬ ‫‪And so ad infinitum.‬‬ ‫‪And the great fleas themselves , in turn‬‬ ‫‪Have greater fleas to go on‬‬


‫محیط برنامه سازی لینوکس‬

‫‪18/322‬‬

‫‪While these again have greater still,‬‬ ‫‪And greauer still , and so on.‬‬ ‫‪W poem‬‬ ‫‪263‬‬ ‫‪q‬‬ ‫‪$‬‬ ‫اولین فرمان سطرها‪ ،‬کلمات و کاراکترها را در يك يا تعداد بیشتری از فايلها مي‌شمرد و اين فرمان پس از نقش شمارش لغات تحت‬ ‫عنوان ‪ wc‬از آن ياد مي‌شود‬

‫‪$ wc poem‬‬ ‫‪8 46 263 poem‬‬ ‫‪$‬‬ ‫يعني‪ ،‬شعر ‪ 8‬سطر‪ 46 ،‬لغت و ‪ 263‬کاراکتر دارد‪ .‬تعريف " کلمه" بسیار ساده است هر رشته ‌(رديفي ) از کاراکترها که حاوی جای‬ ‫خالي فاصله يا سطر جديد نباشد کلمه نامیده مي‌شود‪ Wc .‬بیش از يك فايل برای شما مي‌شماردـ ( و کل آن را چاپ مي‌کند) و‬

‫همچنین هر کدام از شمارشها را در وصورتي که شما از آن بخواهید‪ ،‬متوقف مي‌سازد‪ wc)‌1( .‬را مورد مطالعه قرار دهید‪.‬‬

‫دومین فرامین ‪ grep‬نامیده مي‌شود و اين فرمان فايلها يا سطرهايي که يك الگو را هماهنگ مي‌سازد را جستجو مي کند ‌(نام آن از‬

‫‪ )g/reguler-expression/p‬فرمان ‪ ed‬اقتباس مي‌شود که در بخش ضمیمه ‪ 1‬توضیح داده شده است) فر ض کنید شما مي‌خواهید به‬ ‫دنبال کلمه " ‪ " flea‬در شعر بگرديد‪:‬‬

‫‪$ grep fleas poem‬‬ ‫‪greu flead have little flead‬‬ ‫‪And little fleas have gesser fleas,‬‬ ‫‪Have gret fleas themselves , in turn,‬‬ ‫‪Have greater fleas to go on,‬‬ ‫‪$‬‬ ‫‪ grep‬به دنبال سطرهايي مي‌گردد که با الگو مطابق نیستند‪ ،‬البته زمانیکه انتخاب –‪ v‬به کار برده شود‪ ( .‬اين انتخاب درس از فرمان‬

‫ويراستاری " ‪ " V‬نامیده مي‌شود‪‌،‬مي‌توانید در مورد آن به عنوان معکوس موضوع تطابق‪‌،‬فکر کنید)‪.‬‬

‫‪$ grep - V fleas poem‬‬ ‫‪upon their backs To bile, em,‬‬ ‫‪and so an infinitum.‬‬ ‫‪While these again have greater still,‬‬ ‫‪And greater still , and so on.‬‬ ‫‪$‬‬ ‫‪ grep‬مي‌تواند برای جستجوی چندين فايل مورد استفاده قرار گیرد‪ ،‬در اين صورت‪ ،‬اين فرمان نام فايل را در هر سطری که با آن‬

‫هماهنگ است به پیشوند مي‌آورد بنابراين شما مي توانید تشخیص دهید که اين هماهنگي و تطابق در کجا اتفاق افتاده است‪ .‬همچنین‬

‫انتخابهای برای شمارش‪ ،‬تعداد و از اين قبیل موارد‪ ،‬وجود دارد ‪ grep‬همچنین تعداد زيادی از الگوهای پیچیده را تحت کنترل در‬

‫مي‌آورد تا اينکه تنها يك کلمه مثل ‪ " "fleas‬را کنترل کند اما ما نظرمان را در مورد آن تا رسیدن به فصل ‪ 4‬به تأخیر مي اندازيم‪.‬‬

‫سومین فرمان ‪ sort‬است که وروديهای درون خودرا به ترتیب الفبا سطر به سطر طبقه‌بندی مي‌کند‪ .‬اين موضوع برای شعر چندان جالب‬ ‫نیست‪‌،‬اما اجازه دهید که اينکار را به صورت ديگری انجام دهیم و فقط ببینید که اين مورد شبیه به چیست‪:‬‬

‫‪$ sort poem‬‬ ‫‪and greater sTill, and so on.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪19/322‬‬

‫‪And so ad infinitum.‬‬ ‫‪Have greater fleas To go on,‬‬ ‫‪Upon their backs to bite,em,‬‬ ‫‪And little fleas have lesser fleas,‬‬ ‫‪And the greater fleas themselves , in Turn,‬‬ ‫‪great fleas have little fleas,‬‬ ‫‪while these again greater still,‬‬ ‫‪$‬‬

‫طبقه بندي به صورت سطر به سطر است اما‪ ،‬ترتيب طبقه‌بندي ناقص باعث مي‌شود كه‬ ‫در ابتدا جاي خالي قرار گيرد‪ ،‬سپس حروف بزرگ و سپس حروف كوچك‪‌،‬بنابراين اين‬ ‫شرايط دقيقًا براساس الفبا نمي‌باشد ‪ sort‬داراي هزاران انتخاب جهت كنترل ترتيب طبقه‌بندي‬ ‫است كه عبارتند از‪:‬‬

‫ترتیب معکوس‪‌،‬ترتیب عددی‪ ،‬ترتیب لغت نامه‌ای ‪‌،‬ناديده گرفن فضاهای خالي مهم‪ ،‬طبقه‌بندی بر اساس فايلهای درون سطر و غیره اما‬

‫معمول فرد بايد جهت اطمینان از آنها‪ ،‬آن انتخابها را بررسي کند‪ .‬در اينجا‪ ،‬فهرستي از معمولترين طبقه بندی وجود دارد‪.‬‬

‫معکوس کردن ترتیب معمولي‬

‫‪Sort - v‬‬

‫طبقه بندی به ترتیب عددی‬

‫طبقه بندی به ترتیب عددی معکوس‬

‫‪ Fold upper‬و حروف کوچك با هم ديگر‬ ‫شروع طبقه بندی در میدان‬

‫‪Sort - n‬‬ ‫‪Sort - nr‬‬ ‫‪Sort-f‬‬ ‫‪Sort +n‬‬

‫‪n+1-st‬‬

‫فصل ‪ 4‬دارای اطلعات بیشتری پیرامون ‪ Sort‬است‪.‬‬

‫فرمان بررسي فايل ديگری نیز وجود دارد که تحت عنوان ‪ Tail‬است که ‪ 10‬سطر آخر فايل را چاپ مي‌کند‪ .‬اين فرمان برای هشت‬

‫سطر شعر ما کفايت مي‌کند‪ .‬اما بريا فايلهای بزرگتر مناسب است‪ .‬علوه‌ بر اين‪ Tail ،‬برای مشخص نمودن تعدادسطرها دارای انتخاب‬ ‫است‪ ،‬بنابراين به منظور چاپ آخرين سطر شعر‪:‬‬

‫‪$ Tail -1 poem‬‬ ‫‪and greater still,and so on‬‬

‫‪$‬‬ ‫‪ Tail‬همچنین مي‌تواند برای چاپ فايلي که در يك سطر مشخص شده شروع مي‌شود‪ ،‬به کار برده شوند‪:‬‬

‫‪$ tail +3 filename‬‬ ‫چاپ با خط سوم شروع مي‌شود ( به معکوس بودن طبیعي علمت منها برای شناسه‌ها توجه کنید) جفت فرامین نهايي برای مقايسه‬

‫فايلها در نظر گرفته شده‌اند‪ .‬فرض کنید که ما نوعي شعر در فايل ‪ New – poem‬داريم‪:‬‬

‫‪$ cat poem‬‬ ‫‪Great fleas have little fleas‬‬ ‫‪upon their back to bite em ,‬‬ ‫‪And little fleas have leser fleas,‬‬ ‫‪and so ad infinitum.‬‬ ‫‪And the great fleas themselves , in turn,‬‬ ‫‪Have greater fleas to go on,‬‬ ‫‪While these again have greater still,‬‬ ‫‪And greater still , and so on.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪20/322‬‬

‫‪$ cat Newpoem‬‬ ‫‪Great fleas have little fleas‬‬ ‫‪Upen their back to bite them,‬‬ ‫‪And little fleas have greater fleas,‬‬ ‫‪and so on ad infinitum‬‬ ‫‪And the great fleas themselves, in Turn,‬‬ ‫‪have greater fleas to go on,‬‬ ‫‪while these again have greater still,‬‬ ‫‪and greater still ,and so on.‬‬ ‫‪$‬‬ ‫تفاوت چنداني بین دو فايل وجود ندادر‪‌،‬در حقیقت‪ ،‬شما برای پیدا کردن آن بايد سخت به دنبال آن بگرديد‪ ،‬اين همان فرامین مقايسه‬ ‫فايلها است که يك فرمان مناسب و کاربردی است‪ cmp .‬اولین جايي را که دو فايل از يکديگر متفاوت هستند را پیدا مي‌کند‪:‬‬

‫‪$ cmp poem new-poem‬‬ ‫‪Poem new-poem differ : char 58, line 2‬‬

‫اين فرمان مي‌گويد که اين فايلها در سطر دوم از يکديگر متفاوتند که اين مورد کامل صحیح است ‪ .‬اما اين فرمان نمي‌گويد که تفاوت‬

‫در چیست و علوه بر اين هیچ گونه از تفاوتهايي را که وجود دارد مشخص نمي‌کند يکي ديگر از فرامین مقايسه فايلها فرمان ‪diff‬‬

‫است که در مورد تمام سطرهايي که تغییر يافته‌اند‪ ،‬اضافه شده‌اند و يا حذف شده‌اند‪ ،‬گزارش مي‌دهد‪:‬‬

‫‪$ diff poem new-poem‬‬ ‫‪2c2‬‬ ‫‪< upon their backs to bileem,‬‬ ‫…‬ ‫‪>upon Their backs to bite them,‬‬ ‫‪4 c4‬‬ ‫‪<and so ad infinitum.‬‬ ‫…‬ ‫‪>and so on ad infinitum.‬‬ ‫‪$‬‬ ‫اين فرمان مي‌گويد که سطر ‪ 2‬در اولین فايل ( فايل شعر) به سطر ‪ 2‬فايل ( شعرجديد) تغییر يافته است و به همین صورت در مورد‬

‫سطر چهارم‪ .‬به طور کليـ ‪ cmp‬زماني استفاده مي‌شود که شما بخواهید مطمئن شويد که دو فايل به طور واقعي دارای يك محتوا‬ ‫هستند‪ .‬کار اين فرمان سريع بوده و در هر نوع فايلي کار مي‌کند نه در متن تنها ‪ diff‬زماني استفاده مي‌شود که فايلها تا حدی متفاوت به‬

‫نظر برسند و شما بخواهید واقع ًا بدانید که کدام سطر متفاوت است‪ .‬فرمان ‪ diff‬تنها در فايلهای متني اجرا مي‌شود‪.‬‬

‫خلصه‌ای از فرامین فايلهای سیستم‬ ‫جدول ‪ 1-1‬خلصه‌ای از فرامیني است که ما تاکنون در ارتباط با فايلها از آنها صحبت کرده‌ايم‪.‬‬

‫‪3‬ـ ‪  1‬اطلعات بيشتري در مورد فايلها فهرست راهنما‬ ‫سیستم فايل شما را که تحت عنوانـ ‪ junk‬است ازفايل فرد ديگری که به همین نام است‪‌،‬متمايز مي‌شناسد‪ .‬اين تمايز به وسیله‬


‫محیط برنامه سازی لینوکس‬

‫‪21/322‬‬

‫گروه‌بندی فايلها به فهرستها‪ ،‬صورت مي‌پذيرد که اين فرآيند نسبتاً به ترتیبي است که کتابها در کتابخانه‌ها بر روی قفسه‌ها جای داده مي‬

‫شوند‪ ،‬بنابراين فايلهايي که در فهرستهای متفاوت هستند مي‌توانند بدون هیچ گونه تضادی دارای يك نام باشند‪ .‬به طور کلي هر کاربر‬

‫دارای يك فهرست شخصي و خصوصي است‪ ،‬بعضي اوقات تحت عنوان فهرست ‪ login‬از آن ياد مي‌شود‪ ،‬که تنها حاوی فايلهايي‬

‫است که متعلق به آن فرد است‪ .‬زماني که شما با سیستم ارتباط برقرار مي‌کنید‪ ،‬در واقع شما در فهرست شخصي خودتان هستید‪.‬‬

‫ممکن است فهرستي را که شما در حال کارکردن در آن هستید را تغییر دهید غالباً فهرست کنوني و آن فهرستي را که در حال فعالیت بر‬

‫روی آن هستید را مشخص کنید اما در اين شرايط فهرست شخصي شما هنوز به همان صورت قبلي باقي است‪ .‬مگر اينکه شما عمل‬ ‫خاصي را انجام دهید مثلً زمانیکه يك فايل جديد ايجاد کنید در واقع اين فايل وارد فهرست کنوني شما مي‌شود از آنجايي که اين فايل‬

‫به عنوان فهرست شخصي شما است‪ ،‬در واقع اين فايل به فايلي با همان نام که ممکن است در فهرست شخص ديگری باشد‪ ،‬در واقع‬ ‫اين فايل به فايلي با همان نام که ممکن است در فهرست شخص ديگری باشد‪ ،‬مربوط نمي‌شود‪ .‬فهرست مي‌تواند حاوی فهرستهای‬ ‫ديگر و نیز افیلهای معمولي باشد ‌(فهرستهای بزرگ دارای فهرستهای کوچکتر هستند)‪.‬‬

‫روش معمول برای به تصوير کشیدن اين سازماندهي شبیه به درختي از فهرستها و فايلها است‪ .‬اين امکان وجود دارد که پیرامون هر‬ ‫کدام از اين درختها حرکت کرده و هر کدام از اين فايلهای درون سیستم را به وسیله شروع مسیر از ريشه درخت و حرکت به دنبال‬

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

‫آنها هستید را چاپ مي‌کند‪:‬‬


‫محیط برنامه سازی لینوکس‬

‫‪22/322‬‬

‫جدول ‪ 1-1‬فرمانهای رايج فايل سیستم‬

‫نام‌هايتتت تتتتمامتتت تتتفايلهايتتت تتتموجودتتت تتتدرتتت تتتفهرستتتتتتت (دايركتوري)‬

‫راتتت تتتفهرستتتت تتتمي‌كند‬

‫‪s-1‬‬

‫تنهاتتتتتتت تتتتتتتفايلهايتتتتتتت تتتتتتتنام‌گذاريتتتتتتت تتتتتتتتشدهتتتتتتت تتتتتتتتراتتتتتتت تتتتتتتفهرستتتتتتتت تتتتتتتمي‌كند‬

‫‪1s filenames‬‬

‫بهت تتترتيب ت تتزمانيت تتفهرستت تتمي‌كند‪،‬ت تتآنهايي ت تتكهت تتاخيراً تتبوجود ت تتآمدهت تتدرت تتابتدا ت تتقرارت تتگرفته‌اند‬ ‫‪1s-t‬‬

‫ليستيتتتت تتتتطويلتتتت تتتتوتتتت تتتتشاملتتتت تتتتاطلعاتتتتت تتتتزيادتتتت تتتتوتتتت تتتتنيزتتتتتتتت ‪ 1s-1t‬ميتتتت تتتتباشد‬ ‫‪1s-1‬‬

‫برتت تتاساستت تتآخرينتت تتزمانتت تتموردتت تتاستفادهتت تتقرارتت تتگرفتنتت تتفهرستتت تتمي‌شودتت تتوتت تتنيزتت تتشامل‬ ‫‪1s-u‬‬ ‫‪ 1s-1u,1s-1ut‬نيز مي‌باشد‪.‬‬

‫بهتتت تتتترتيبتتت تتتمعكوستتت تتتفهرستتتت تتتمي‌شودتتت تتتوتتت تتتنيزتتت تتتشاملتتتتت ‪ rt,-rlt-‬وتتت تتتغيرهتتت تتتمي‌باشد‬

‫‪1s-r‬‬

‫فايلهايتتتتتتتت تتتتتتتتنامتتتتتتتت تتتتتتتتگذاريتتتتتتتت تتتتتتتتشدهتتتتتتتت تتتتتتتتراتتتتتتتت تتتتتتتتويراستاريتتتتتتتت تتتتتتتتمي‌كند‬ ‫‪ed - filename‬‬ ‫‪ File‬را به ‪ 2file‬كپي كرده و در صورتي كه‬ ‫‪1 file 2‬‬ ‫‪ file 2‬آن را جانويسي مي‌كند‪.‬‬

‫‪cp file‬‬

‫‪file2‬‬

‫فايلهاي نام‌گذاري شده را پاك كرده ‪‌،‬البته اين عمل‬

‫‪rm filename‬‬

‫به صورت تغییر ناپذير صورت مي‌گیرد‬

‫محتواهايتتتتتتت تتتتتتتفايلهايتتتتتتت تتتتتتتنام‌گذاريتتتتتتت تتتتتتتشدهتتتتتتت تتتتتتتراتتتتتتت تتتتتتتچاپتتتتتتت تتتتتتتمي‌كند‬

‫‪cat filenames‬‬

‫محتواهاتتتتتتتتتتت تتتتتتتتتتتراتتتتتتتتتتت تتتتتتتتتتتباتتتتتتتتتتت تتتتتتتتتتتسرآمدتتتتتتتتتتت تتتتتتتتتتتچاپتتتتتتتتتتت تتتتتتتتتتتمي‌كند‬ ‫‪pr filenames‬‬

‫‪ 66‬سطر را در هر صفحه‬

‫درتتتتتتتتتتتتتتتتتتتت تتتتتتتتتتتتتتتتتتتتستونهايتتتتتتتتتتتتتتتتتتتتتتتتتتتتتتتتتتتتتتت ‪ n‬چاپتتتتتتتتتتتتتتتتتتتت تتتتتتتتتتتتتتتتتتتتمي‌كند‬

‫‪pr-n flienames‬‬

‫فايلهاي نام‌گذاري شده را در كنار هم چاپ مي‌كند‬

‫‪pr-m flie‬‬

‫‪names‬‬

‫(ستونهای چندگانه)‬

‫سطرها‪ ،‬لغات و كاراكترها را براي هر فايل مي‌شمرد‬

‫‪wc‬‬

‫‪flienames‬‬

‫سطرهاتتتتتتتتتتت تتتتتتتتتتتراتتتتتتتتتتت تتتتتتتتتتتبرايتتتتتتتتتتت تتتتتتتتتتتهرتتتتتتتتتتت تتتتتتتتتتتفايلتتتتتتتتتتت تتتتتتتتتتتمي‌شمارد‬ ‫‪wc-1 filenames‬‬

‫سطرهاي هماهنگ با الگو با چاپ مي‌كند‬

‫‪grep pattern‬‬

‫‪flienames‬‬

‫سطرهايي كه هماهنگ با الگو نباشد را چاپ مي‌كند‬

‫‪grep-v‬‬

‫‪pattern files‬‬

‫فايلها را به صورت الفبايي و به صورت سطري چاپ مي‌كند‬

‫‪sort‬‬

‫‪filenames‬‬

‫‪ 10‬سطرتتتتتتتتتتت تتتتتتتتتتتآخرتتتتتتتتتتت تتتتتتتتتتتفايلتتتتتتتتتتت تتتتتتتتتتتراتتتتتتتتتتت تتتتتتتتتتتچاپتتتتتتتتتتت تتتتتتتتتتتمي‌كند‬ ‫‪tail filename‬‬ ‫‪ n‬سطر آخر فايل را چاپ مي‌كند‬ ‫چاپ فايل را در سطر ‪ n‬شروع مي كند‬

‫‪filename Tail - n‬‬ ‫‪Tail +n filename‬‬


‫محیط برنامه سازی لینوکس‬

‫‪23/322‬‬

‫محل اولين تمايز را چاپ مي‌كند‬

‫‪filel filez‬‬

‫تمام تفاوتهاي موجود بين فايلها را چاپ مي‌كند‪.‬‬ ‫‪pwd $‬‬ ‫‪usr/you/‬‬ ‫‪$‬‬

‫‪cmp‬‬ ‫‪diff filel filez‬‬

‫اين فرمان مي‌گويد که شما در حال حاضر در فهرست خودتان و در دايرکتوری ‪ usr‬هستید که به نوبة خود اين فهرست در فهرست‬ ‫ريشه قرار دارد‪ ،‬که اين فهرست به صورت قراردادی «م» نامیده مي‌شود‪ .‬علمت ‪ /‬اجزاء نام را از يکديگر جدا مي‌کند؛ محدودة ‪14‬‬

‫کاراکتری که در بال ذکر شد برای هر جزء که چنین نامي حاوی فهرستهای تمام کاربردن سیستم است ‪( .‬حتي اگر فهرست اصلي شما به‬

‫صورت ‪ usr/you/‬نباشد‪ ،‬در اين صورت ‪ pwd‬چیزی شبیه به آن را چاپ خواهد کرد و بنابراين شما بايد قادر باشید‪ ،‬آنچه را که در‬ ‫زير اتفاق مي‌افتد‪ ،‬پیگیری کنید)‪ .‬اگر اکنون شما‬

‫‪$‬‬

‫‪ 1S/usr/you‬را تايپ کنید‪ ،‬دقیقا ً همان فهرست نامهای فايلي را دريافت مي‌کنید که شبیه به آنچه مي‌باشد که از ‪ 1S‬معمولي‬

‫دريافت کرده‌ايد‪ .‬زمانیکه هیچ شناسه‌ای فراهم نباشد و ‪ 1S‬محتواهای فهرستهای معمول را فهرست مي‌کند‪ ،‬و نام دايرکتوريها را نشان‬

‫مي دهد و محتوای آن دايرکتوری را فهرست مي‌کند‪ .‬سپس برای اجرای ‪$‬‬

‫‪ 1S/usr‬تلش کنید‪ ،‬اين فرمان بايد يك سری طويلي از‬

‫نامها را چاپ کنید که در بین آنها دايرکتوری متعلق به شما نیز وجود دارد‪ .‬مرحلة بعدی تلش برای فهرست کردن خود ريشه است‪ .‬در‬

‫اين وضعیت جوابي شبیه به اين نمونه دريافت مي‌کنید‪:‬‬

‫‪$‬‬

‫‪/ 1S‬‬ ‫‪bin‬‬ ‫‪boot‬‬ ‫‪dev‬‬ ‫‪etc‬‬ ‫‪lib‬‬ ‫‪tmp‬‬ ‫‪unix‬‬ ‫‪usr‬‬ ‫‪$‬‬

‫(در مورد دو معناي ‪ /:‬دچار سردرگمي نشويد‪ ،‬اين دو معنا‪ ،‬نام ريشه بوده و در نامهاي‬ ‫فايها نقش جداكننده دارد)‪ .‬اغلب اينها فهرستها هستند‪ ،‬اما یونيکس فايلي است كه‬ ‫حاوي شكل قابل اجراء هستة اصلي یونيکس است‪ .‬اطلعات بيشتر پيرامون اين موضوع‬ ‫در فصل ‪ 2‬آورده شده است‪ .‬اكنون فرمان ‪$‬‬ ‫(اگر ‪ junk‬هنوز در فهرست شما وجود دارد)‪.‬‬

‫‪ cat / usr/usr/you/junk‬را انجام دهيد‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪24/322‬‬

‫نامت ‪ usr/you/junk/‬تحت تعنوانت ‪( path name‬نام تمسير) فايل تنام تدارد‪ Pathnam .‬داراي تمعناي‬ ‫مستقيم است‪ ،‬و نام كامل مسير را از ريشهت (در سرتاسر درخت دايركتوري) به فايل‬ ‫خاص‪ ،‬تنشان تمي‌دهدت ‪ .‬اين تموضوع‪ ،‬تقانون تكلي تدرت تسيستم تیونيکس تاست تكهت تشما‬ ‫مي‌توانيد تازت تنام تفايل تمعمولي تيا تاز تنام تمسير تاستفاده تكنيد‪ .‬فايل تسيستم تشبيه تبه‬ ‫شجرهت تنامت تشكل تگرفته تاست‪ :‬درت تاينجات تتصويري توجود تدارد تكهت تاين تموضوع ترات تشفافتر‬ ‫مي‌سازد‪.‬‬ ‫‪Boot‬‬

‫‪bin‬‬

‫‪unix‬‬

‫‪tmp‬‬ ‫‪mary‬‬

‫‪data‬‬

‫‪junk‬‬

‫‪usr‬‬ ‫‪paul‬‬

‫‪etc‬‬ ‫‪mike‬‬

‫‪temp‬‬

‫‪Dev‬‬ ‫‪Jou‬‬

‫‪junk‬‬

‫‪Junk‬‬

‫فايل شما که ‪ junk‬نام دارد به فايل ‪ paul‬يا ‪ Mary‬مربوط نمي‌باشد‪ .‬نامهای مسیرها در صورتي موجود نمي‌باشند که تمام فايلهای‬

‫موردتوجه در دايرکتوری شما باشند‪ ،‬اما درصورتي که شما با دايرکتوری فرد ديگری يا با چندين طرح به صورت همزمان سروکار داشته‬ ‫باشید‪ ،‬به راستي آنها قابل استفاده مي شوند‪ .‬برای مثال دوست شما مي‌تواند ‪ junk‬شما را با اظهار ‪ cat/usr/you/junk $‬چاپ کند‪ ،‬به‬

‫طر مشابهي‪ ،‬شما نیز مي‌توانید با اظهار‬

‫‪$ 1S/usr/mary‬‬ ‫‪data‬‬ ‫‪junk‬‬ ‫‪$‬‬ ‫متوجهـ ـشويدـ ـکهـ ‪ Mary‬چهـ ـفايلهاييـ ـدارد‪،‬ـ ـياـ ـيكـ ـکپيـ ـازـ ـفايلهایـ ـاوـ ـراـ ـبرایـ ـخودـ ـتهیهـ ـکنید‪،‬ـ ـکهـ ـاينـ ـعملـ ـباـ ـفرمانـ ‪$‬‬

‫‪ cp/usr/mary/data data‬انجام مي‌شود‪ ،‬يا فايل او را ويراستاری کنید‪:‬‬

‫‪ $ ed/usr/mary/data‬در صورتي که ‪ Mary‬نخواهد شما پیرامون فايلهايش جستجو کنید و يا برعکس‪ ،‬محیط خصوصي مي‌تواند‬

‫در اين شرايط تنظیم شود‪ .‬هر فايل و دايرکتوری اجازة اجراء خواندن ـ نوشتن برای مالك آن‪ ،‬گروه و هر فرد ديگری را دارد که‬

‫مي‌تواند جهت کنترل دسترسي به آن‪ ،‬مورد استفاده قرار گیرد‪ 1( .‬ـ ‪ 1S‬را به خاطر آوريد‪ ).‬در سیسمتهای محلي ما اغلب کاربران‪ ،‬اغلب‬

‫اوقات از محیط باز نسبت به محیط خصوصي‪ ،‬مزايای بیشتری دريافت مي‌کنند اما اين روش شايد در سیستم شما متفاوت باشد‪،‬‬

‫بنابراين راجع به اين موضوع در فصل ‪ 2‬مجدداً بحث خواهیم‌کرد‪ .‬به‌عنوان آخرين مجموعة تجربیات درمورد ناجهای مسیرها‪ ،‬فرمان ‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪25/322‬‬

‫‪ 1S/bin/usr/bin‬را اجراء کنید‪ .‬آيا برخي از نامها آشنا به نظر مي‌رسند؟ زماني که شما يك فرمان را به وسیله تايپ کردن نام آن پس از‬

‫آماده شدن‪ ،‬اجراء مي‌کنید‪ ،‬سیستم برای فايلي که به آن نام است به جستجو مي‌پردازد ‪ .‬به طور طبیعي اين فايل ابتدا در فهرست‬

‫(دايرکتوری) شما ظاهر مي‌شود‪( ،‬احتمال ً آن فايل را در کجا نمي‌توان يافت) ‪ ،‬بعد از دايرکتوری شما در ‪ bin/‬و نهايتا ً در ‪usr/bin/‬‬

‫يافت مي‌شود‪ .‬هیچ موضوع خاصي پیرامون فرامیني شبیه ‪ 1S‬يا ‪ cat‬وجود ندارد‪ ،‬بر غیر از اينکه‪ ،‬آنها در يك جفت دايرکتوری جمع‬

‫آوری شده‌اند‪ ،‬تا اينکه جهت فرايند جستجو و اجراء به آساني پیدا شوند‪ .‬به منظور اثبات اين موضوع‪ ،‬تلش کنید که برخي از اين‬ ‫برنامه‌ها را با استفاده از نامهای مسر کاملشان اجراء کنید‪:‬‬

‫‪/ $‬‬

‫‪bin/date‬‬

‫‪23 : 29 : 32 EDT 1983‬‬ ‫‪22:20‬‬ ‫‪22:40‬‬ ‫‪23:04‬‬

‫‪26‬‬ ‫‪26‬‬ ‫‪26‬‬

‫‪26‬‬ ‫‪sep‬‬ ‫‪sep‬‬ ‫‪sep‬‬

‫‪Mon sep‬‬ ‫‪bin/who / $‬‬ ‫‪Srm‬‬ ‫‪tty/‬‬ ‫‪Crw‬‬ ‫‪ttJ4‬‬ ‫‪you‬‬ ‫‪tty5‬‬ ‫‪$‬‬

‫تمرين ‪3‬ـ ‪  S/usr/games /  $ :1‬را اجراء كنيد‪ .‬‬ ‫و هر آنچه را که به طور طبیعي پیش مي‌آيد را انجام دهید‪ .‬اين اتفاقات ممکن است خارج از زمان کاری طبیعي‪ ،‬سرگرم کننده‌تر به نظر‬

‫برسد‪.‬‬

‫تغيير‪ ‬دادن‪ ‬دايركتوري ـ ‪ cd‬‬ ‫درصورتي که شما بهصورت منظم با مری (‪ )Hary‬در مورد اطلعات موجود در فهرستش در ارتباط باشید‪ ،‬مي‌توانید بگوئید «من‬

‫مي‌خواهم به جای کارکردن بر روی فايل خودم‪ ،‬بر روی فايل مری کار کنم »‪ .‬اين فرايند با تعويض فهرست خودتان بافرمان‬

‫‪cd‬امکان‌پذير است‪cd/usr/Mary $:‬‬

‫اکنون زمانیکه شما از يك نام نام (بدون ‪ ) ’/ S‬به عنوان شناسه برای برای ‪ cat‬يا ‪ pr‬استفاده کنید‪ ،‬اين عمل بر فايلي در فهرست ‪،Mary‬‬

‫دللت دارد‪ .‬تغییر دايرکتوريها تحت تأثیر هیچ‌گونه اجازة مربوط به فايلها نمي‌باشد‪ ،‬درصورتي که شما نتوانید به فايلي از دايرکتوری‬

‫خودتان دسترسي پیداکنید‪ ،‬آن را به دايرکتوری ديگری که تغییر نخواهد کرد‪ ،‬تغییر دهید ‪ .‬اين موضوع کامل ً مناسب است که فايلهای‬

‫شخصي‌تان را منظم کنید‪ ،‬بنابراين تمام فايلهايي که به يك چیز مربوط مي‌شوند در يك دايرکتوری جداگانه‌ای از ديگر موضوعات قرار‬

‫مي‌گیرد‪ .‬برای مثال‪ :‬درصورتیکه شما بخواهید کتابي بنويسید‪ ،‬ممکن است بخواهید تمام متن را در يك دايرکتوری که کتاب نام دارد‪،‬‬

‫حفظ و نگهداری کنید‪ .‬فرمان ‪ mkdir‬باعث بوجود آمدن دايرکتوری جديد مي‌شود‪.‬‬

‫دايرکتوری جديد بساز‬

‫رفتن به محل موردنظر‬

‫از اينکه در محل صحیح قرار گرفته‌ايد اطمینان حاصل کنید‪.‬‬

‫‪mkdir book $‬‬ ‫‪cd book $‬‬ ‫‪pwd $‬‬


‫محیط برنامه سازی لینوکس‬

‫‪26/322‬‬

‫‪usr/you/book/‬‬ ‫نوشتن کتاب موردنظر (پس از گذشتن چند دقیقه)‬

‫…‬

‫به میزان يك سطح بالرفتن (جابه جا شدن) در فايل سیستم‬

‫…‪$ cd‬‬ ‫‪$ pwd‬‬ ‫‪/usr/you‬‬ ‫‪$‬‬ ‫’‪ ‘ ..‬به منشاء همان دايرکتوری که شما معمولً در آن قرارداريد دللت مي‌کند و دايرکتوری يك سطح به ريشه نزديك‌تر مي‌شود ‪‘ 0 ’ .‬‬ ‫مترادفي است برای دايرکتوری فعلي‪ ،‬به دايرکتوری اصلي برمي‌گردد‪.‬‬ ‫‪$‬‬

‫‪cd‬‬

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

‫(روش سريعتر و کوتاهتر را به شما خواهیم آموخت)‪ ،‬سپس فرمان ‪ cd‬را در دايرکتوری اصلي کتاب اجراء کرده و ‪$‬‬

‫‪rmdir book‬‬

‫را تايپ کنید‪ rmdir ،‬تنها دايرکتوری خالي را حذف خواهد کرد‪.‬‬

‫‪ ‌4  ‬ت‪ Shell  1  ‬‬ ‫زمانیکه سیستم پیغام ‪ $‬را چاپ کرد و شما فرامیني را تايپ کرديد که اجراء شوند ‪ .‬اين هسته اصلي (‪ )kernel‬نیست که با شما مرتبط‬ ‫مي‌شود بلکه ‪ go-between ،‬فرمان تعبیر و تفسیر ياـ ‪ Shell‬را فراخواني مي‌کند‪ Shell .‬تنها يك برنامة معمولي شبیهـ ‪ date‬ياـ ‪who‬‬

‫است‪ ،‬اگر اين برنامه مي‌تواند کارهای قابل توجهي انجام دهد‪ .‬اين حقیقت که ‪ Shell‬بین شما و امکانات هسته اصلي (‪ )Kernel‬جای‬ ‫گرفته است‪ ،‬واقعیت دارد‪ ،‬ما در مورد برخي از موارد آن در اينجا صحبت خواهیم کرد‪ .‬سه نکته اصلي وجود دارد‪:‬‬

‫• مختصرت تنويسي تنامت تفايلها‪ :‬مي‌توانيدت تمجموعةت تكامليت تازت تنامهايت تفايلهات ترات تبهت تعنوان‬ ‫شناسه در برنامه‌اي به وسيلة خصوصي سازي الگويي براي نامها‪ ،‬بدست آوريد‪Shell ،‬‬ ‫نامهاي فايلهايي را پيدا مي‌كند كه با الگوي شما هماهنگي دارد‪.‬‬ ‫• تغيير مسير ورودي ت خروجي ‪ :‬مي‌توانيد خروجي هر برنامه را به جاي رفتن به پايانه‪،‬‬ ‫طوري تنظيم كنيد كه به فايل وارد شود و در مورد ورودي طوري ترتيب دهيد كه ورودي به‬ ‫جاي تپايانه تازت تفايل تنشأت تگيرد‪ .‬ورودي توت تخروجي تحتي تمي‌توانند تبه تديگربرنامه‌ها تنيز‬ ‫متصل شوند‪.‬‬

‫• خصوصي سازي محيط‪ :‬مي‌توانيد فرامين شخصي‌تا و مختصر نويسي را بدين وسيله‬ ‫تشريح كنيد‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪27/322‬‬

‫مختصر نويسي نام فايل‬ ‫اجازه دهید با الگوهای نام فايلها شروع کنیم‪ .‬فرض کنید در حال تايپ کردن سند بزرگي همچون کتاب هستید‪ .‬از لحاظ منطقي اين‬

‫سند بايد به قطعات بسیار کوچك مثل فصل و شايد بخش تقسیم شود‪ .‬اساساً چنین تقسیم‌بندی بايد صورت گیرد‪ ،‬اين فرايند به منظور‬

‫ويراستاری فايلهای بزرگ امری دشوار است‪ .‬بنابراين‪ ،‬بايد آن سند را به صورت تعداد فايلها تايپ کنید‪ .‬ممکن است فايلها را برای هر‬

‫فصل جدا کنید و آنها را فصل ‪ ،1‬فصل ‪ 2‬و … نام‌گذاری کنید‪ .‬يا در صورتیکه هر فصل به بخشهايي تقسیم شود‪ ،‬ممکن است فايلهايي‬

‫ايجاد کنید که‬

‫فصل ‪2 .1‬‬

‫فصل ‪1 .1‬‬

‫فصل ‪2 .1‬‬

‫فصل ‪1 .2‬‬ ‫فصل ‪1 .3‬‬

‫………‬

‫نام داشته‌ باشد که اين عمل سازماندهي خاصي است که ما برای اين کتاب استفاده‌ کرده‌ايم ‪ .‬به کمك يك سیستم نامگذاری قراردادی‬

‫مي‌توانید با يك نگاه اجمالي تعیین کنید که يك فايل خاص در کدام محل با کل فايلها تناسب پیدا مي‌کند ‪ .‬چه بخشهايي از کل کتاب را‬ ‫مي‌خواهید چاپ کنید؟ در اين مورد مي‌توانید بگوئید ‪:‬‬

‫‪$‬‬

‫‪ch 1.3‬‬

‫‪ch 1.1 ch 1.2‬‬

‫‪…… pr‬‬

‫اما به زودی از تايپ کردن نامهای فايلها خسته شده و شروع به غلط نوشتن مي‌کنید‪ .‬اين جا همان مرحله‌ايي است که مختصر نويسي‬ ‫نام فايلها وارد عمل مي‌شود‪ .‬درصورتي که بگوئید ‪*pr ch $‬‬

‫‪ Shell‬علمت * رابه معنای ‘هر رديفي از کاراکترها’ تلقي مي‌کند‪ ،‬بنابراين ‪ *ch‬الگويي است که تمام نامهای فايلها را که در دايرکتوری‬

‫فعلي همراه ‪ ch‬هستند را هماهنگ مي‌کند‪ Shell .‬لیستي فراهم مي‌آورد که به ترتیب الفايي است و لیست را به ‪ pr‬انتقال مي‌دهد‪ .‬فرمان‬

‫‪ pr‬هرگز علمت * را نمي‌بیند‪ ،‬الگوهايي که ‪ Shell‬را هماهنگ کرده‌اند در دايرکتوری فعلي لیستي از رديفهای کاراکتری را بوجود‬

‫مي‌آورند که به ‪ pr‬انتقال داده مي‌شود‪ .‬مرحلة بحراني‪ ،‬عبارتست از مرحله‌ايي که مختصر نويسي نام فايلها خصوصیت فرمان ‪ pr‬نباشد‪،‬‬

‫اما کار برنامة ‪ Shell‬باشد‪ .‬بنابراين مي‌توانید از آن برای تولید توالي نامهای فايلها برای هر فرمان استفاده کنید‪ .‬برای مثال‪ ،‬برای شمردن‬ ‫کلمات در اولین فصل‪:‬‬

‫‪chl.0‬‬ ‫‪chl.1‬‬ ‫‪chl.2‬‬ ‫‪chl.3‬‬ ‫‪chl.4‬‬ ‫‪chl.5‬‬ ‫‪chl.6‬‬ ‫‪ToTal‬‬

‫‪3200‬‬ ‫‪22435‬‬ ‫‪22756‬‬ ‫‪8481‬‬ ‫‪28841‬‬ ‫‪2030‬‬ ‫‪2030‬‬ ‫کل) ‪3801‬‬

‫*‪ch.1.‬‬ ‫‪562‬‬ ‫‪4081‬‬ ‫‪4191‬‬ ‫‪1561‬‬ ‫‪5298‬‬ ‫‪194‬‬ ‫‪323‬‬ ‫‪16210‬‬

‫‪$ wc‬‬ ‫‪113‬‬ ‫‪935‬‬ ‫‪974‬‬ ‫‪378‬‬ ‫‪1293‬‬ ‫‪33‬‬ ‫‪75‬‬ ‫‪)88933‬‬

‫برنامه‌ای به نام ‪ echo‬وجود دارد که برای بررسي معنای کاراکترهای مختصرنويسي بسیار مفید است‪ .‬همانطور که حدس مي‌زنید‪echo ،‬‬

‫چیزی به غیر از انعکاس شناسه‌هايش انجام نمي‌دهد‪:‬‬

‫‪world‬‬

‫‪hello‬‬ ‫‪world‬‬

‫‪$‬‬ ‫‪echo‬‬ ‫‪hello‬‬ ‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪28/322‬‬

‫اما شناسه‌ها مي‌توانند به وسیله تطابق الگويي‪ ،‬گسترش يابند‪:‬‬ ‫تمام نامهای‪ ،‬کلیة فايلهای موجود در فصل ‪ 1‬را فهرست کنید‪.‬‬ ‫تمام نامهای فايلهای موجود در دايرکتوری فعلي را به ترتیب حروف الفبايي فهرست کنید‪.‬‬

‫*‪echo ch1‬‬

‫‪$‬‬

‫* ‪echo‬‬

‫‪$‬‬

‫* ‪$ pr‬‬

‫تمام فايلهای خودتان (به ترتیب حروف الفبايي) را چاپ کنید‪ ،‬و‬

‫* ‪$ rm‬‬ ‫تمام فايلهای موجود در دايرکتوری فعلي خود را پاك کنید‪( .‬بهتر است که از آنچه که مي‌خواهید بگوئید‪ ،‬مطمئن شويد!) ‪ .‬علمت * به‬ ‫آخرين وضعیت در نام فايلها محدود نمي‌شود ـ ‪ * ’S‬هرجايي مي‌تواند باشد و چندين بار نیز مي‌تواند‪ ،‬اتفاق افتد‪ .‬بنابراين ‪$‬‬

‫‪rm‬‬

‫‪ * save‬تمام فايلها را که با ‪ save‬پايان مي‌يابد را پاك مي‌کند‪ .‬توجه داشته باشید که نامهای فايلها به ترتیب الفايي طبقه بندی شده‌اند‪،‬‬

‫که اين طبقه بندی همانند ترتیب عددی نیست‪ .‬اگر کتابتان دارای ‪ 10‬فصل است‪ ،‬ترتیب آن ممکن است آنچیزی که موردنظر شما‬

‫است‪ ،‬نباشد‪ ،‬از اين رو فصل ‪ 10‬قبل از فصل ‪ 2‬قرار مي‌گیرد‪:‬‬

‫‪$‬‬

‫‪* echo‬‬

‫‪Ch 1.1 ch1.2... ch10.1 ch10.2 ...ch2.1 ch2.2...‬‬ ‫‪$‬‬ ‫علمت * تنها خصوصیت تطابق الگو نیست که به وسیلة ‪ Shell‬فراهم مي‌شود‪ ،‬اگرچه اين علمت به میزان زيادی مورد استفاده قرار‬ ‫مي گیرد‪ .‬الگوی [‪ ]...‬هرکدام اگر کاراکترهای موجود در براکت را هماهنگ مي‌سازد ‪ .‬محدوده‌ايي از حروف متوالي يا ارقام مي‌توانند به‬

‫صورت مختصر نوشته شوند‪.‬‬

‫* [‪pr ch ]1 2 3 4 6 7 8 9‬‬

‫فصلهای ‪9‬و ‪8‬و ‪7‬و ‪6‬و ‪4‬و ‪3‬و ‪2‬و ‪ 1‬به غیر از ‪ 5‬را چاپ کن‬ ‫همین عمل را انجام بده‬

‫‪$‬‬

‫‪* ]pr ch ]1-46-9 $‬‬

‫‪ Tempz, Temp‬كه ‪]rm Temp ]a-z $‬‬

‫هركدام از‬ ‫موجود است را پاك کن‬

‫الگوی ؟ هرگونه کاراکتر تنها (مجزا) را مطابقت مي‌دهد‪:‬‬

‫فايلها را با نامهای مجزای کاراکترها فهرست کن‬

‫‪$‬‬

‫فصل ‪1‬ـ ‪ ، 1‬فصل ‪1‬ـ ‪ ، 2‬فصل ‪1‬ـ ‪ 3‬و…‬

‫‪$‬‬

‫‪ch? .1‬‬

‫‪? 1S‬‬ ‫‪1S-1‬‬

‫را فهرست کن اما فصل ‪1‬ـ ‪ 10‬را فهرست نکن‬

‫فايلهای ‪ ...Temp 1 ، Tempa‬و غیره را پاك کن‬

‫‪$‬‬

‫‪?rm Temp‬‬

‫توجه داشته باشید که الگوها تنها نامهای فايلهای موجود را تطبیق مي‌دهند‪ .‬به ويژه شما نمي‌توانید نامهای فايلهای جديد را با استفاده از‬ ‫الگوها‪ ،‬تنظیم کنید‪ .‬برای مثال‪ ،‬اگر بخواهید ‪ ch‬را هر نام فايل به ‪ chapter‬گسترش دهید‪ ،‬نمي‌توانید اين کار را به اين نحو انجام دهید‪:‬‬ ‫عملي نیست!‬

‫‪$‬‬

‫‪ch.* chapter‬‬

‫‪*.mv‬‬

‫زيرا * ‪ chapter .‬هیچ نام فايل موجودی را تطبیق نمي‌دهد کاراکترهای الگو شبیه * مي‌توانید در نامهای مسیر و نیز نامهای فايلها ساده‬

‫استفاده شوند و اين تطابق برای هر جزء مسیر که حاوی کاراکتر خاص باشد صورت مي‌پذيرد ‪ .‬بنابراين ‪ */usr/Mary/‬اين تطابق را در‬


‫محیط برنامه سازی لینوکس‬

‫‪29/322‬‬

‫‪ usr/mary/‬انجام مي‌دهد و ‪ usr/*/calendar/‬لیست نامهای فايلها تمام کاربران فايلهای ‪ calendar‬را توسعه مي‌دهد‪.‬‬

‫درصورتي که بخواهید برای همیشه معنای خاص * ‪ ،‬؟ و غیره را استفاده نکنید‪ ،‬در اين صورت کل شناسه را در علمت نقل قول ‪،‬‬

‫همانند‬

‫‪? 1S $‬‬ ‫قراردهید‪ .‬همچنین مي‌توانید‪ ،‬کاراکتر خاصي را با ‪ backslash‬در تقدم قرار دهید‬

‫‪? \ 1s $‬‬ ‫(به خاطر داشته باشید‪ ،‬از آنجايي که؟ علمت از بین بردن سطر يا پاك کن نیست‪ ،‬اين ‪ backslash‬به وسیلة ‪ shell‬تعبیر و تفسیر‬ ‫مي‌شود نه بوسیلة هسته اصلي «‪ .) »kernd‬نقل قول به طور مفصل در فصل ‪ ،3‬بحث شده است‪.‬‬

‫تمرين ‪4‬ـ ‪ )1‬تفاوتهای موجود بین اين فرامین چیست؟‬

‫‪$ echo junk‬‬ ‫‪$ echo /‬‬ ‫‪$ echo‬‬ ‫* ‪$ echo‬‬ ‫* ‪$ echo‬‬

‫‪$‬‬ ‫‪1S junk‬‬ ‫‪$ 1S /‬‬ ‫‪$ 1S‬‬ ‫‪$ 1S‬‬ ‫* ‪$ 1S‬‬

‫تغيير جهت ورودي ـ خروجي‬ ‫اغلب فرمانهايي که ما تاکنون ديده‌ايم خروجي را در پايان بوجود مي‌آورند و برخي نیز مانند ويراستار‪ ،‬ورودی آنها از پايانه نشأت گرفته‬ ‫است ‪ .‬اين امر تقريبا ً کلي است که پايانه بتواند به وسیله فايل برای ورودی و خروجي به صورت دوتايي يا برای هکردام به صورت‬ ‫مجزا جايگزين شود‪ .‬به عنوان مثال‪:‬‬

‫‪$‬‬

‫‪ 1S‬لیستي از نامهای فايلها بر روی پايانة شما ايجاد مي‌کند‪ .‬اما درصورتي که بگوئید‬

‫‪1S > file list‬‬ ‫چنین لیست يکساني از نامهای فايلها در عوض در فايل ‪ ، filelist‬قرار خواهد گرفت‪ .‬علمت < به معنای اين است که‪:‬‬

‫‪$‬‬

‫«خروجي را در فايل بعدی قرار دهید به جای اينکه در پايانه قرار دهید»‬

‫فايل درصورتي ايجاد خواهد شد که پیش از اين وجود نداشته باشد يا محتواهای قبل درصورتي که آن فايل وجود داشته باشد‪ ،‬روی‬ ‫هم نوشته شده باشد‪.‬‬

‫هيچ چيزي بر روي پايانة شما ايجاد نمي‌شود‪ .‬به عنوان مثال ديگر‪ ،‬مي‌توانيد چندين فايل‬ ‫را در يك فايل به وسيله اشغال (ذخيره سازي) خروجي ‪ cat‬در يك فايل تركيب كنيد‪:‬‬ ‫‪cat f1 f2 f3 > temp $‬‬ ‫علمت << بیشتر کاری شبیه < را انجام مي‌دهد‪ ،‬به غیر از اين مورد اين علمت به معنای «افزودن به قسمت انتهای فايل» نیز مي‌باشد‪.‬‬ ‫يعني‪:‬‬

‫‪cat f1f2f3 >> temp‬‬

‫‪$‬‬

‫محتواي ‪ f1 f2 f3‬را در پايان هرآنچه كه از قبل در ‪ Temp‬وجود داشته‪ ،‬به جاي نوشتن بر روي‬ ‫محتواهاي موجود‪ ،‬كپي مي‌كند‪ .‬در موردت < (درصورتي كهت ‪ Temp‬وجود نداشته باشد) در‬ ‫ابتدا باعث بوجود آوردن يك فايل خالي براي شما مي شود‪ .‬به روشي مشابه ‪ ،‬علمت >‬ ‫به معناي گرفتن ورودي از پايانه گرفته شود‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪30/322‬‬

‫بنابراين‪ ،‬مي‌توانید نامهای را در فايل ‪ let‬آماده کرده و سپس آن را به وسیله ‪ mail mary joe Tom bob<leT $‬به چندين نفر‬

‫بفرستید‪ .‬در تمام اين مثالها‪ ،‬جاهای خالي در هر طرف از <‪ >or‬اختیاری مي‌باشد‪ ،‬اما قالب بندی ما ‪ ،‬قديمي است‪ .‬با نشان دادن قابلیت‬

‫تغییر مسیر خروجي با < ‪ ،‬باعث مي‌شود که اين فرايند برای ترکیب فرمانهای به منظور تأثیر گذاری که به هیچ نحو ديگر امکان پذير‬ ‫نیست‪ ،‬ممکن و میسر شود‪ .‬برای مثال‪ ،‬به منظور چاپ فهرست الفبايي از کاربران‪،‬‬

‫‪$ who > temp‬‬ ‫‪S sort < temp‬‬ ‫از اين رو ‪ who‬يك سطر از خروجي را در هر ارتباط کاربر چاپ مي‌کند و ‪ wc-1‬سطرها را مي‌شمارد (شمارش کلمات و کاراکترها را‬ ‫متوقف سازيد) به اين ترتیب مي توانید کاربران را با‬

‫‪$ who > temp‬‬ ‫‪$ wc – 1 < temp‬‬ ‫شمارش کنید‪ .‬مي‌توانید فايلهای موجود در دايرکتوری فعلي را با‬

‫‪$ Is > temp‬‬ ‫‪$ wc – 1 < temp‬‬ ‫با اين وجود اين فايل شامل نام فايل ‪ temp‬است که خودش هم در شمارش محسوب مي شود‪ .‬مي‌توانید نامهای فايلها را در ستونهای‬

‫درختي شکل با‬

‫چاپ کنید‪ .‬و مي‌توانید بینید که کاربر ويژه‌ايي به وسیله ترکیب ‪ who‬و ‪ grep‬ارتباط برقرار کرده است‬

‫‪IS > temp‬‬ ‫‪pr – 3 < temp‬‬

‫‪$‬‬ ‫‪$‬‬

‫‪$ who > temp‬‬ ‫‪$ grep mary < temp‬‬ ‫در تمام اين مثالها‪ ،‬کاراکترهای الگوی نام فايل مثل * ‪ ،‬اين نکته مهمي است که به خاطر آوريد‪ ،‬تعبیر و تعريف علمت > و < به وسیله‬ ‫‪ shell‬صورت مي‌پذيرد نه به وسیله برنامه‌های خاص‪ .‬تمرکز بخضي امکانات درـ ‪ shell‬به اين معناست که تغییر جهت ورودی و‬

‫خروجي مي‌‌تواند با هر برنامه ای مورد استفاده قرار گیرد؛ خود برنامه متوجه نیست که اتفاقي در حال رخ دادن است‪.‬‬

‫اين امر باعث مي‌شود قانون مهمي مطرح شود‪ .‬فرمان ‪ sort < temp $‬محتواهای فايل ‪ temp‬را طبقه‌بندی مي‌کند‪ ،‬همانگونه که ‪$‬‬

‫‪ sort temp‬اين کار را انجام مي‌دهد‪ ،‬اما تفاوتي در اين فرايند وجود دارد‪ .‬از آنجايي که رشته > ‪ temp‬به وسیله ‪ shell‬تفسیر مي شود‪،‬‬ ‫‪ sort‬نام فايل ‪ temp‬را به عنوان يك شناسنامه‪ ،‬تشخیص نمي‌دهد و آن در عوض ورودی استاندارد خودش را طبقه‌بندی مي‌کند‪ ،‬به‬

‫نحوی که ‪ shell‬دارای برنامه تغییر مسیر است‪ ،‬بنابراين اين فرايند نشأت گرفته از فايل است‪ .‬آخرين نمونه نام ‪ temp‬را به عنوان‬

‫شناسه به ‪ sort‬انتقال مي‌دهد که باعث خواندن فايل و طبقه‌بندی آن مي‌شود‪ Sort .‬مي‌تواند فهرستي از نامهای فايل‌ها را مثل ‪sort $‬‬

‫‪ temp1 temp2 temp3‬ارائه دهد اما ‪ ،‬اگر هیچ نام فايلي ارائه نشود‪ ،‬اين برنامه وروديهای استاندارد خودش را طبقه‌بندی مي‌کند‪.‬‬ ‫اين فرايند خصوصیت ضروری اغلب فرمانها است ‪ :‬در صورتي که هیچ نام فايلي مشخص نشود‪ ،‬ورودی استاندارد‪ ،‬پردازش مي‌شود‪.‬‬

‫اين امر به اين معناست که شما مي‌توانید به سادگي برای اينکه متوجه شويد آنها چگونه کار مي‌کنند‪ ،‬در فرمانها تايپ کنید ‪ .‬برای مثال‬ ‫‪$‬‬

‫‪sort‬‬ ‫‪ghi‬‬ ‫‪abc‬‬ ‫‪CTL –d‬‬ ‫‪Abc‬‬


‫محیط برنامه سازی لینوکس‬

‫‪31/322‬‬

‫‪Def‬‬ ‫‪ghi‬‬ ‫‪$‬‬

‫در بخش بعدی‪ ،‬ما خواهیم ديد که اين اصل چگونه مورد استفاده قرار مي‌گیرد‪.‬‬ ‫تمرين ‪6‬ـ ‪ ، 1‬خروجي از ‪$‬‬

‫‪Temp > Temp‬‬

‫درصورتي که نام فرمان را غلط نوشته باشید‪ ،‬همانند ‪$‬‬

‫‪ WC‬را شرح دهید‪.‬‬

‫‪ who > Temp‬چه اتفاقي مي‌افتد؟‬

‫تمام مثالها در پايان بخش قبلي بر روی يك راهکار تکیه دارد‪ :‬خروجي يك برنامه را د ورودی برنامة ديگری از طريق يك فايل موقتي‬

‫قرار دهید‪ .‬اما فايل موقتي هیچ هدف ديگری ندارد‪ ،‬به راستي اين فايل به منظور مورد استفاده قرار گرفتن چنین فايلي نامناسب است‪.‬‬

‫اين نتیجه منجر به يکي از بخشهای اصلي سیستم يونیکس که همان لوله است مي‌شود‪ .‬لوله روشي است برای اتصال خروجي يك‬ ‫برنامه به ورودی برنامة ديگر بدون هیچ فايل موقتي؛ خط لوله عبارتست از اتصال دو يا تعداد بیشتر برنامه کاز طريق لوله‌ها‪ .‬اجازه دهید‬ ‫برخي از مثالهای پیشین را به منظور استفاده از لوله‌‌ها به جای فايلهای موقتي‪ ،‬مورد بررسي مجدد قرار دهیم‪ .‬کاراکترهای ستونهای‬

‫عمودی به ‪ Shell‬اعلم مي‌کند که خط لوله را تنظیم کند ‪:‬‬ ‫لیست فهرست بندی شده کاربران را چاپ کنید‪.‬‬

‫کاربران را شمارش کنید‬

‫لیست ‪ 3‬ستوني از نامهای فايلها‬

‫به دنبال کاربر ويژه جستجوکردن‬

‫‪who : sert $‬‬ ‫‪who : wc-1 $‬‬ ‫‪1S : wc-1 $‬‬ ‫‪who : grep mary $‬‬

‫هر برنامه‌ای که از پايانه خوانده شود مي‌تواند به جای آن از لوله نیز خوانده شود و هر برنامه‌ای که در پايانه نوشته شود مي‌تواند در لوله‬

‫نیز نوشته شود‪ .‬اين نقطه جايي است که قراردادن خوانده عبارتست از ورودی استاندارد‪ ،‬البته زماني که هیچ فايل نامگذاری شده‬

‫سودمند نباشد‪.‬‬

‫هر برنامه‌ای که بر اين قرارداد پیوندد مي‌تواند در خطوط لوله مورد استفاده قرار گیرد‪ Grep، pr، sort .‬و ‪ wc‬همگي از روشي استفاده‬ ‫مي‌کنند که در خط لوله ذکر شده مي‌توانید تعداد بسیاری از برنامه‌های موجود در خط لوله را داشته باشید‪:‬‬

‫اين فرمان لیست سه ستوني از نامهای فايلها بر روی مطر چاپگر ايجاد مي‌کند و‬

‫‪|S : pr-3: | pr‬‬

‫‪$‬‬

‫‪$ who : grep mary : we –1‬‬ ‫تعداد دفعاتي که ‪ Mary‬ارتباط برقرار کرده است را مي‌شمرد‪ .‬برنامه‌ها در خط لوله به همان تعداد مي‌رسند‪ ،‬البته نه يکي پس از ديگری‪.‬‬ ‫اين فرايند به اين معناست که برنامه‌ها در خط لوله مي‌توانند دوسويه عمل کنند‪ ،‬هسته اصليـ (‪ )Kernel‬هرآنچه که برنامه‌ريزی و‬

‫هماهنگ سازی به منظور آماده کردن آن برای انجام تمام کارها‪ ،‬لزم دارند را مورد تعقیب قرار مي‌دهد ‪ .‬زمانیکه شما دچار حدس و‬

‫گمان شويد‪ Shell ،‬کارها را هنگامي که شما درخواست لوله کنید‪ ،‬تنظیم مي‌کند؛ برنامه‌های خاصي وجود دارند که از آن بي‌اطلع بوده‬ ‫و به منظور تغییر مسیر به کار مي‌روند‪ .‬البته برنامه ها درصورتي که به اين ترتیب ترکیب شوند‪ ،‬به صورت معقولنه عمل خواهند نمود‪.‬‬

‫اغلب فرمانها طرح معمولي و عادی را دنبال مي‌کنند‪ ،‬بنابراين آنها به طرز مناسبي در خطوط لوله و در هر موقعیتي‪ ،‬تطبیق مي‌يابند‪ .‬به‬ ‫طور طبیعتي ‪ ،‬استمداد و کمك گرفتن از فرماني به اين صورت مي‌باشد‪:‬‬


‫محیط برنامه سازی لینوکس‬

‫‪32/322‬‬

‫‪ Command optonal - arguments - Tianal - filenames‬درصورتي كه هيچ نام فايلي ارائه نشود‪،‬‬ ‫فرمان ورودي استاندارد خودش را كه ناشي از نقص پايانه است (جهت آزمايش مناسب‬ ‫است) را مي‌خواند اما‪ ،‬اين موضوع مي‌تواند به منظور ناشي شدن از يك قايل يا لوله‬ ‫تغيير جهت دهد‪ .‬در همين زمان‪ ،‬در قسمت خروجي‪ ،‬اغلب فرمانها خروجيشان را بر روي‬ ‫يك خروجي استاندارد‪ ،‬مي‌نويسند‪ ،‬كه اين جريان همراه با نقصي به پايانه انتقال مي‌يابد‪.‬‬

‫اما اين خروجي مي‌تواند در يك فايل يا لوله تغيير جهت پيدا كند‪ .‬پيغامهاي خطا از ناحية‬ ‫فرمانها به طر متفاوتي كنترل مي‌شود‪ ،‬و يا ممكن است آنها در يك فايل را در قسمت‬ ‫پايين لوله ناپديد شوند‪ .‬بنابراين هر فرمان داراي يك خروجي خطاي استاندارد است كه به‬ ‫طور طبيعي به سمت پايانه شما جهت گرفته است‪ .‬يا به صورت تصويري عبارتست از‪:‬‬

‫‪standard‬‬

‫‪command,‬‬

‫‪output‬‬

‫‪options‬‬

‫‪Standard input‬‬ ‫‪Or files‬‬

‫‪Standard error‬‬

‫تقريباً تتمامت تفرمانهاييت تكهت تمات تتاكنونت تدرموردت تآنهات تصحبتت تكرديمت تبات تاينت تمدلت تسازگار‬ ‫مي‌باشند؛ت تتنهات تاستثناءت تدرت تفرمانهاييت تهمچون ت ‪ date‬و ت ‪ who‬استت تكهت تهيچت توروديت ترا‬ ‫نمي‌خوانند‪ ،‬و به ميزان كمي شبيه ‪ cmp‬و ي ‪ diff‬است كه دارد تعداد ثابتي از وروديهاي‬ ‫فايل هستند‪( .‬اما به انتخاب ‘‪ ‘-‬در اين موارد توجه كنيد)‪.‬‬

‫تمرين ‪7‬ت ‪ )1‬تفاوت بين‬

‫‪$‬‬

‫‪who / sort‬‬ ‫‪who > sort $‬‬

‫را توضيح دهيد‪.‬‬

‫پردازش‬

‫‪ Shell‬علوه بر تنظيم لوله‌ها چند كارايي ديگر نيز دارد‪ .‬اجازه دهيد به طور خلصه بيشتر به‬ ‫جاي پرداختن به برنامه‌ها به نوبت به اصول اجراي آنها بپردازيم‪ ،‬چرا كه ما پيش از اين‬


‫محیط برنامه سازی لینوکس‬

‫‪33/322‬‬

‫تاحدودي به اين موضوع در ارتباط با لوله‌ها پرداختيم براي مثال‪ ،‬مي‌توانيد دو برنامه را با‬ ‫يك فرمان به وسيله جدا كردن فرمانها با استفاده ا نقطه ويرگول ) ؛ت ) اجراء كنيد‪،‬ت ‪Shell‬‬ ‫نقطه ويرگول ( ؛ ) را تشخيص داده و خط فرمان را به دو فرمان مجزا مي‌شكند‪:‬‬ ‫‪date ; who $‬‬ ‫‪1983‬‬

‫‪01:03:17‬‬

‫‪EDT‬‬

‫‪sep‬‬

‫‪27‬‬

‫‪Tue‬‬

‫‪00:43‬‬

‫‪27‬‬

‫‪sep‬‬

‫‪TTJo‬‬

‫‪Ten‬‬

‫‪23:45‬‬

‫‪26‬‬

‫‪sep‬‬

‫‪Tly 1‬‬

‫‪Dmr‬‬

‫‪23:59‬‬

‫‪26‬‬

‫‪sep‬‬

‫‪TTJ2‬‬

‫‪Rob‬‬

‫‪00:06‬‬

‫‪27‬‬

‫‪sep‬‬

‫‪TTJ3‬‬

‫‪Bwk‬‬

‫‪23:31‬‬

‫‪26‬‬

‫‪sep‬‬

‫‪TTJ4‬‬

‫‪Jj‬‬

‫‪23:04‬‬

‫‪sep 26‬‬

‫‪Tty5‬‬

‫‪You‬‬

‫‪23:34‬‬

‫‪sep 26‬‬

‫‪TTJ7‬‬

‫‪Ber‬‬

‫‪$‬‬ ‫هر دو فرمانها (به ترتيب) قبل از اينكه ‪ sell‬با يك كاراكتر پيغامي برگردد‪ ،‬اجراء مي‌شوند‪.‬‬

‫شما نيز مي‌توانيد به صورت همزمان درصورت تمايل بيش از يك برنامه اجراء كنيد‪ .‬براي‬ ‫مثال‪ :‬فرض كنيد مي خواهيد كار وقت گيري مثل شمردن لغات كتابتان را انجام دهيد‪ ،‬اما‬ ‫نمي‌خواهيد كه صبر كنيد تا ‪ WC‬قبل از اينكه شما مشغول كار ديگري شويد‪ ،‬تمام شود‪.‬‬ ‫در اين صورت مي‌توانيد بگوئيد‪:‬‬ ‫‪$‬‬ ‫فرايند ‪ id‬به وسيله ‪ shell‬چاپ مي‌شود‪.‬‬

‫‪& WC ch * > . out‬‬ ‫‪6944‬‬ ‫‪$‬‬

‫آمپرساند & در پايان خط فرمان به ‪ shell‬مي‌گويد‪« :‬اجراي اين فرمان را شروع كن‪ ،‬سپس‬ ‫فرمانهاي بيشتري را از پايانه سريعاً بگير» ‪ ،‬يعني منتظر تكميل آن نشو‪ .‬بنابراين‪ ،‬فرمان‬ ‫شروع خواهد شد‪ ،‬اما شما درحاليكه اين فرمان در حال اجراء است مي‌توانيد كار ديگري‬ ‫انجام دهيد‪ .‬جهت گيري خروجي به فايل ‪ WC.out‬آن را از مداخله با هر آنچه كه شما در‬ ‫همان فرمان در حال انجام آن هستيد‪ ،‬حفظ مي‌كند‪ .‬نمونه‌اي از اجراي برنامه‪ ،‬پردازش‬ ‫ناميده مي‌شود‪ .‬اعدادي كه به وسيلة ‪ shell‬براي فرمانها چاپ مي‌شود‪ ،‬با & آغاز شد و‬


‫محیط برنامه سازی لینوکس‬

‫‪34/322‬‬

‫تحت عنوان ‪ process- id‬نام گرفت؛ مي‌توانيد ا آن در فرمانهاي ديگري براي رجوع به برنامة‬ ‫در حال اجراي خاص ديگري استفاده كنيد‪ .‬اين نكتة مهمي است كه بين برنامه‌ها و‬ ‫پردازش‌ها تمايز قائل شويم‪ WC .‬يك برنامه است‪ ،‬هر بار كه شما برنامة ‪ WC‬را اجراء كنيد‪،‬‬ ‫اين برنامه پردازش جديدي ايجاد مي‌كند‪ .‬اگر چندين نمونه از برنامه‌هاي يكسان در يك‬ ‫زمانت تدرت تحالت تاجراءت تباشند‪،‬ت تهركدامت تبات ‪ process-id‬متفاوتيت تبهت تصورتت تجداگانهت تپردازش‬ ‫مي‌شوند‪ .‬درصورتي كه خط لوله با & شروع شود‪ ،‬مثل ‪$‬‬

‫‪& pr ch* |pr‬‬ ‫‪/695‬‬

‫‪precess-id of |pr‬‬ ‫‪$‬‬

‫پردازش در آن‪ ،‬در يك زمان شروع مي‌شود ت & در تمام خطوط لوله بكار برده مي‌شود‪ .‬تنها‬ ‫يك ‪ process-id‬پردازشهاي نهايي در تواليها‪ ،‬چاپ مي‌شود‪ .‬فرمان ت ‪$‬‬

‫‪ wait‬تا زماني صبر‬

‫مي‌كند كه تمام پردازشهاي آغازشده با & پايان پذيرد‪ .‬درصورتي كه اين پردازش سريعًا باز‬ ‫نگردد‪ ،‬به اين معناست كه شما هنوز فرمان در حال اجراء داريد‪ .‬مي‌توانيد فرمان ‪ wait‬را با‬ ‫‪ delete‬قطع كنيد‪ .‬مي‌توانيد ازت ‪ precess-id‬كه بوسيله ‪ shell‬چاپ مي‌شود براي متوقف كردن‬ ‫فرايند پردازش آغاز شده با & ‪ ،‬استفاده كنيد‪:‬‬ ‫‪kill 6944 $‬‬

‫درصورتيكهت تشمات ‪ process-id‬رات تفراموشت تكنيد‪،‬ت تمي‌توانيدت تازت تفرمانت ‪ ps‬برايت تاطلعت تيافتن‬ ‫پيرامون هرآنچه كه شما در نظر داريد اجراء كنيد‪ ،‬استفاده كنيد‪ .‬اگر كار شما بي‌نتيجه‬ ‫بود‪ kill O ،‬تمام پردازشهاي شما را به غير از ارتباط شما با ‪ shell‬را از بين مي‌برد‪ .‬اگر شما‬ ‫در مورد آنچه كه ديگر كاربران انجام مي‌دهند كنجكاو هستيد‪ ps-ag ،‬به شما در مورد تمام‬ ‫پردازشهايي كه در حال اجراء است اطلعاتي مي‌دهد‪ .‬در اينجا نمونه‌هايي از خروجيها‬ ‫آورده شده است‪:‬‬ ‫‪$‬‬ ‫‪CMD‬‬

‫‪TIMe‬‬

‫‪/etc/Cron 36‬‬ ‫‪6423‬‬ ‫‪0:02‬‬ ‫‪6704‬‬

‫‪Tty‬‬ ‫‪6:29‬‬

‫‪PID‬‬ ‫‪Co‬‬

‫‪5‬‬ ‫ ‪Sh‬‬‫‪1‬‬

‫‪0:04‬‬

‫‪Sh -‬‬

‫‪ps - ag‬‬


‫محیط برنامه سازی لینوکس‬

‫‪35/322‬‬

‫‪6722‬‬

‫‪1‬‬

‫‪0:12 1‬‬

‫‪vi paper‬‬

‫‪4430‬‬

‫‪2‬‬

‫‪0:03‬‬

‫‪Sh -‬‬

‫‪6722‬‬

‫‪1‬‬

‫‪0:12‬‬

‫‪fi paper‬‬

‫‪4430‬‬

‫‪2‬‬

‫‪0:03‬‬

‫‪Sh-‬‬

‫‪6612‬‬

‫‪7‬‬

‫‪0:03‬‬

‫‪Sh-‬‬

‫‪6628‬‬

‫‪7‬‬

‫‪1:13‬‬

‫‪rogue‬‬

‫‪6843‬‬

‫‪2‬‬

‫‪0:02‬‬

‫‪write dmr‬‬

‫‪6949‬‬

‫‪4‬‬

‫‪0:01‬‬

‫‪login birnmler‬‬

‫‪6952‬‬

‫‪5‬‬

‫‪0:08‬‬

‫‪ch1.1 ch 1.2 ch 1.3 ch1.4‬‬

‫‪6951‬‬

‫‪5‬‬

‫‪0:03‬‬

‫‪1pr‬‬

‫‪6950‬‬

‫‪5‬‬

‫‪0:02‬‬

‫‪ps – ag‬‬

‫‪6844‬‬

‫‪1‬‬

‫‪0:02‬‬

‫‪reb‬‬

‫‪pr‬‬

‫‪write‬‬

‫‪$‬‬ ‫‪ PID‬عبارتست ازت ‪ process-id ، TTJ‬پايانه‌اي همراه با پردازش استت (همانندت ‪who( ; TIME‬‬

‫عبارتست از پردازشگر زمان كه در دقايق و ثانيه ها به كار برده مي‌شود‪ ،‬و مابقي فرماني‬ ‫است كه بايد اجراء شود‪ PS .‬يكي از آن فرمانهايي است كه در انواع متفاوت سيستمها ‪،‬‬ ‫متفاوت است‪ ،‬بنابراين خروجي شما ممكن نيست كه مانند اين مورد قالب بندي شود‪.‬‬ ‫درصورتيكه شناسه‌ها ممكن است متفاوت باشند (در اين مورد به صفحه فهرست (‪Ps )1‬‬

‫مراجعه كنيد‪ ).‬پردازشها تداراي تيك نوع طبقه تبندي ساختار سلسله تمانند تهستند كه‬ ‫فايلها نيز دارند‪ .‬هر پردازش داراي مبداء بود و شايد داراي انشعاباتي نيز باشد‪ .‬برنامة‬ ‫‪ Shell‬سيستم شما با پردازشي همراه با هر آنچه كه شما به خط پايانة سيستم متصل‬ ‫كرده‌ايد‪ ،‬ايجاد مي‌شود‪ .‬همان زماني كه شما فرمانها را اجراء مي‌كنيد‪ ،‬آن پردازشها‬ ‫انشعابات برنامة ‪ Shell‬سيستم شما را كنترل و هدايت مي‌كنند‪ .‬در صورتيكه شما يكي از‬ ‫برنامه‌هاي‌موجود تدرت تيكي تازت تآنت تپردازشها ترات تاجراءت تكنيد‪،‬ت تبراي تمثال تفرمانت ‪ 1‬بهت تمنظور‬ ‫رهايي از ‪،ed‬‬ ‫در اين صورت آن پردازش پردازش انشعاب متعلق به خودش كه انشعاب اصلي ‪ Shell‬است‬ ‫را ايجاد مي‌كند‪ .‬بعضي اوقات پردازش تا زماني طول مي‌كشد كه شما بخواهيد اجراء‬ ‫برنامه‌اي را شروع كنيد و سپس پايانه را خاموش كرده و بدون منتظر ماندن براي پايان‬


‫محیط برنامه سازی لینوکس‬

‫‪36/322‬‬

‫پذيري آن به خانه برويد‪.‬‬

‫اما اگر شما پايانه‌تان را خاموش كنيد يا ارتباط خود را قطع كنيد‪ ،‬پردازش به طور طبيعي‬ ‫حتي اگر شما ازت & استفاده كنيد‪ ،‬از بين مي‌رود‪ .‬فرمانت ‪( nohup‬قطع نكردن) به منظور‬ ‫ارتباط با اين موقعيت ايجاد شده است‪‌:‬در صورتي شما اعلم كنيد ‪، & nohup command$‬‬ ‫فرمان حتي اگر شما ارتباط خود را قطع كنيد‪ ،‬تا زمان اجراء ادامه پيدا مي‌كند‪ .‬هر گونه‬ ‫خروجي از فرمان در فايلي كهت ‪ nohup.out‬ناميده مي‌شود‪ ،‬ذخيره مي‌شود‪ .‬هيچ روشي‬ ‫براي ‪ nohup‬به منظور برگشت پذيري فرمان ‪ ‌ ،‬وجود ندارد‪ .‬در صورتيكه پردازش شما تعداد‬ ‫زيادي از پردازشگرهاي منابع اصلي را شامل شود‪ ،‬در واقع اين شرايط لطفي است در‬ ‫حق كساني كه باسيستم شما براي به جريان انداختن شغلتان با هزينه كمتري نسبت‬ ‫به قبل‪‌،‬شريك هستند‪‌،‬اين فرآيند به وسيله برنامة ديگري كه ‪ nice‬ناميده مي‌شود‪ ،‬انجام‬ ‫مي‌شود؛– ‪& nice expencive command $‬‬

‫به طرز خودكار ‪ nice‬ناميده مي‌شود‪‌،‬چرا كه اگر‬

‫شما در نظر داشته باشيد كه ارتباط خود را قطع نمائيد‪ ،‬مي‌توانيد براي داشتن فرماني‬ ‫كه كمي بيشتر طول بكشد‪ ،‬از اين فرمان استفاده كنيد‪ ،‬نهايتاً ‪ ،‬مي‌توانيد به وضوح به‬ ‫سيستم بگوئيد كه پردازش را زمان صبح يعني كه افراد طبيعتاً در خواب به سر مي‌برند‪،‬‬ ‫نه در محاسبه كردن‪ ،‬شروع كند‪ ،‬دين فرمان ‪ )at )1‬نام دارد‪.‬‬ ‫‪at tme $‬‬ ‫‪Whaterer commands‬‬ ‫‪Jeu want‬‬ ‫‪Cti-d‬‬ ‫‪$‬‬ ‫اين مورد كاربرد رايج است اما مسلمًا فرمانها مي‌توانند از فايل نشأت بگيرند‪:‬‬ ‫‪at 3am < fle $‬‬ ‫‪$‬‬

‫زمانها مي‌توانند به سبكت ‪ 24‬ساعته نوشته شود‪ ،‬شبيهت ‪ 2130‬و يا به سبكت ‪ 12‬ساعته‬ ‫‪. 630Pm‬‬ ‫مناسب‪ ‬كردن‪ ‬محيط‪ ‬‬


‫محیط برنامه سازی لینوکس‬

‫‪37/322‬‬

‫يكي از مزاياي سيستم یونيکس اين است كه چندي روش براي نزديك كردن آن به علقه‬ ‫شخصي شما يا قراردادهاي محيط محاسبة محلي شما‪ ،‬دارد‪ .‬براي مثال ما قبل از اين‬ ‫مسئلة استانداردهاي متفاوت را براي پاك كن يا كاراكترهاي از بين برندة سطرها كه با‬ ‫توجه به نقص عبارتند ازت‬

‫¿‬

‫توت @ ‪ ،‬ذكر كرديم‪ .‬شما مي‌توانيد هر زمان كه خواستيد اين‬

‫مورد را با فرمان‬ ‫‪erase , Kill K‬‬

‫‪$‬‬

‫‪STTJ‬‬

‫عوض كنيد ‪( ،‬تغيير دهيد)‪ .‬در اين فرمان ‪ e‬شامل هر كاراكتري است كه شما براي پاك كن‬ ‫در نظر گرفته‌ايد و ‪ K‬براي كاراكتر از بين برندة سطرها در نظر گرفته شده است‪ .‬اما تايپ‬ ‫نمودن اين فرمان هر زمان كه با سيستم مرتبط هستيد‪ ،‬دردسرساز است‪ Shell .‬در اين‬ ‫زمينه باعث رهايي از اين دردسر مي‌شود‪ .‬اگر فايلي تحت عنوانت ‪ . profile‬در دايركتوري‬ ‫ارتباط شما وجود داشته باشد‪ Shell ،‬قبل از چاپ اولين پيغام فرمانها را در آن‪ ،‬هنگامي كه‬ ‫شما ارتباط برقرار كرده‌ايد‪ ،‬اجراء مي‌كند‪ .‬بنابراين‪ ،‬شما مي‌توانيد فرمانها را در ‪ . profile‬به‬ ‫منظور تنظيم محيط پيرامونتان به همان صورت كه دوست داريد‪ ،‬قرار دهيد و آنها (فرمانها)‬ ‫هر زمان كه شما ارتباط برقرار مي‌كنيد‪ ،‬اجراء خواهند شد‪.‬‬ ‫اولين چيزي كه اغلب افراد در ‪ profile‬خود قرار مي‌دهند‪ ،‬عبارتست از‪:‬‬ ‫‪erase‬‬

‫‪STTJ‬‬

‫درت تاينجات تمات تازت ‪ ‬تاستفاده تمي‌كنيم‪ .‬بنابراين تمي‌توانيدت تآنت ترات تببينيدت تامات تمي‌توانيدت تكليد‬ ‫برگشت حروف به عقب (‪ )backspace‬را در ‪ . profile‬خود قرار دهيد‪ STTy .‬نيز ‪ x‬را براي ‪ x‬ت ‪CTL‬‬

‫مي‌فهمد‪ ،‬بنابراين‪ ،‬مي‌توانيد همان اثر را با ‪ erase /h STTy‬دريافت كنيد‪ .‬چرا كه ‪ cTL-h‬همان‬ ‫‪ backspace‬است‪( .‬كاراكترت ‪ ‬تبهت تعنوانت تيكت تهمت تمعني تقديميت تبرايت تاپراتورت تلولهت ت تاست‪،‬‬ ‫بنابراين شما بايد از آن با علمت نقل قول محافظت كنيد)‪ .‬درصورتيكه پايانة شما نقطة‬ ‫‪ Tab‬حساس نداشته باشد ‪ ،‬مي‌توانيد ‪ Tabs‬ت را به خط ‪ STTy‬اضافه كنيد‪:‬‬ ‫‪erase ∧ h - Tabs‬‬

‫‪STTy‬‬

‫اگر علقه‌مند هستيد كه بفهميد اشغال بودن سيستم هنگامي كه با آن مرتبط هستيد‬ ‫چگونه تاست‪،‬ت ‪ who/wc - 1‬رات تاضافه تكنيد‪،‬ت تتات تاينكه تاينت تفرمان تتعداد تكاربران ترات تبشمارد‪.‬‬

‫درصورتيكه سرويس خبري وجود داشته باشد‪ ،‬مي‌توانيدت ‪ news‬را اضافه كنيد‪ .‬بعضي از‬


‫محیط برنامه سازی لینوکس‬

‫‪38/322‬‬

‫مردم‪ ،‬آدمهاي خوش شانس را دوست دارند‪ ،‬بنابراين ‪usr/games/fortune/‬‬

‫بعد از مدتي ممكن است متوجه شويد كه ارتباط برقرار كردن شما‪ ،‬زنان زيادي وقت برده‬ ‫است (بيشتر طول كشيده است)‪ .‬پس به اين منظور ‪ . profile‬خود را قطع كرده و درصورت‬ ‫لزومت تدوباره تارتباطت تبرقرارت تكنيد‪ .‬برخي تازت تخصوصياتت ‪ Shell‬بوسيلة تمتغيرهايت ‪ Shell‬كنترل‬ ‫مي‌شوند‪ ،‬البته با معيارهايي كه شما بتوانيد به آنها دسترسي پيدا كرده و سيستم خود‬ ‫را تنظيم كنيد‪.‬‬ ‫براي مثال‪ ،‬رشته پيغامهايي كه ما به صورت ‪ $‬نشان داده‌ايم‪ ،‬در متغيرهاي ‪ Shell‬كه ‪ps1‬‬

‫ناميده مي‌شوند ذخيره مي‌شوند و شما مي‌توانيد آن را در هرجايي كه دوست داريد تنظيم‬ ‫كنيد‪ ،‬مثل اين مورد‪:‬‬ ‫‪?Ps1= 1yes dear‬‬ ‫علمت نقل قول لزم است چراكه فضاهايي در رشته پيغامها وجود دارد‪.‬‬

‫فضاها پيرامون = در اين ساختار‪ ،‬مجاز نمي‌باشد‪ Shell .‬همچنين متغيرهاي ‪ Hmoe‬و ‪ MaIL‬را‬ ‫مورد بررسي قرار مي‌دهد‪ HOME .‬نام دايركتوري اصلي مشا است و اين دايركتوري به‬ ‫طور طبيعي بدون مجبور بودن به قرار گرفتن در ‪ profile‬تنظيم مي‌شود‪ .‬متغيرها ‪ ، MaIL‬نام‬ ‫فايلهاي استاندارد است يعني جايي كه نامه‌هاي شما حفظ مي‌شود‪ .‬درصورتي كه شما‬ ‫آن را براي ‪ Shell‬تعريف كنيد‪ ،‬بعد از هر فرمان درصورتيكه نامة جديدي برسد به شما اطلع‬ ‫خواهد داد‪.‬‬

‫احتمالً تمفيدترين تمتغيرهايت ‪ Shell‬عبارتندت تازت تمتغيرهايي تكهت تجاهايي تكهت ‪ Shell‬بهت تدنبال‬ ‫فرمانها مي‌گردد را كنترل مي‌كنند‪ .‬به خاطر داشته باشيد كه زمانيكه شما نام فرمان را‬ ‫تايپ تمي‌كنيد‪،‬ت ‪ Shell‬بهت تطور تطبيعتي تاول تدر تدايركتوري تكنوني تبه تدنبال تآن تمي‌گردد تو‬ ‫سپست تدرت ‪ bin/‬وت تبعدت تازت تآنت تدرت ‪ . usr/bin/‬اينت تتواليت تفهرستهات «مسيرت تجستجو» ناميده‬ ‫مي‌شوند و در متغير ‪ Shell‬كه ‪ PATH‬ناميده مي‌شود‪ ،‬ذخيره مي‌شود‪ .‬اگر مسير جستجو‬ ‫آن مسيري نباشد كه شما مي‌خواهيد‪ ،‬مي‌توانيد آن را تغيير دهيد‪ ،‬و معمولً در ‪. profile‬‬ ‫‪11‬ت ايتتن عمل در ‪ Shell‬به نحو بدي انجام مي‌گيرد ‪ .‬پس از اينكه هر فرمان به صورت به بار سيستم افزوده شد‪،‬‬ ‫فايل را مورد بررسي قرار دهيد‪ .‬همچنين‪ ،‬درصورتيكه شما براي مدت طولني در حال كار كردن بر روي برنامه‬ ‫ويراستاري باشيد اطلعاتي در مورد نامه جديد فرا نخواهيد گرفت چرا كه شما فرمانهاي جديد را با ارتباط‬ ‫برقرارت كردن بات ‪ Shell‬اجراء نكرده‌ايد‪ .‬طرح و راهكار بهتر اين است كه هرچند دقيقه يكبار به جاي بعد از هر‬ ‫فرمان‪ ،‬اوضاع را مورد بررسي قرار دهيد‪ .‬فصل ‪ 7‬و ‪ 5‬نشان مي‌دهد كه اين نوع از مرورگرهاي نامه چگونه عمل‬ ‫مي‌كنند‪ .‬سومين امكان كه براي هر فردي موجود نمي‌باشد‪ ،‬اين است كه تنها برنامة پست الكترونيكي خود‬ ‫شما را مطلع بسازد‪ :‬اين شرايط مطمئناً زماني ميسر مي‌شود كه نامه تنها براي شما فرستاده شده باشد‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪39/322‬‬

‫سيستم‌تان اين عمل انجام مي‌گيرد‪ .‬براي مثال‪ :‬اين سطر مسير را به سمت يك مسير‬ ‫استاندارد به علوة ‪ usr/games/‬تنظيم مي‌كند‪.‬‬ ‫‪one way‬‬

‫‪:/ bin ;/usr/bin : /usr/ games‬‬

‫‪...PATH:‬‬

‫اين فرآيند كمي عجيب به نظر مي‌رسد‪ :‬توالي نام دايركتوريها به وسيله ‪ :‬از يكديگر جدا‬ ‫مي‌شوند‪ .‬به خاطر داشته باشيد كه ‘‪ ’.‬همان دايركتوري فعلي است‪ .‬شما مي‌توانيد ‘‪ ’.‬را‬ ‫حذف كنيد و جزء صفر درت ‪ PATH‬به معناي دايركتوري فعلي است‪ .‬راه ديگر براي تنظيم‬ ‫مسير (‪ )PATH‬در اين موردخاص عبارتست‌از افزايش ‌دادن معيار قبلي(‪PATH= $ PATH: /usr‬‬

‫‪ ) /games Anether way‬مي‌توانيد مقدار هرگونه متغيرهاي ‪ Shell‬را به وسيله پيشونددار كردن‬ ‫نام آن با ‪ ، $‬بدست آوريد‪ .‬در مثال بال‪ ،‬حالت ‪ PAHT $‬مقادير فعلي را اصلح مي‌كند‪ ،‬به‬ ‫نحويت تكهت تبخشت تجديد‪،‬ت تافزودهت تمي‌شودت توت تنتايجت تبه ت ‪ PATH‬برگرداندهت تمي‌شود‪ .‬شما‬ ‫مي‌توانيد اين فرايند را با ‪ echo‬اثبات كنيد‪:‬‬ ‫‪$‬‬

‫‪is $ PATH‬‬

‫‪echo PATH‬‬

‫‪PATH is :/bin:/usr/bini /usr/games‬‬ ‫‪$‬‬

‫‪$ HOME‬‬

‫‪echo‬‬

‫‪your legin directory/‬‬

‫‪usr/you‬‬

‫‪$‬‬

‫اگر شما برخي از فرمانهاي مربوط به خودتان را در اختيار داشته باشيد‪ ،‬ممكن است‬ ‫بخواهيد آنها را در دايركتوري مربوط به خودتان جمع‌آوري كرده و آنها را به مسير جستجو‬ ‫شخصي‌تان اضافه نمائيد‪ .‬در اين صورت‪ PATH ،‬شما ممكن است چنين به نظر برسد‪:‬‬ ‫‪PATH= : $ HOME /bin:/bin:/usr/bin:/usr/games‬‬

‫ما در مورد نوشتن فرمانهاي شخصي‌تان در فصل ‪ 3‬خواهيم كرد‪ .‬متغير ديگر كه غالباً به‬ ‫وسيله تزئينات ويراستاري متن استفاده مي‌شود تا به وسيله ‪ ، ed‬عبارتست از ‪ TERM‬كه‬ ‫نام نوعي از پايانه‌هايي است كه شما از آن استفاده مي‌كنيد‪ .‬چنين اطلعاتي ممكن‬ ‫استت تاينت تامكانت ترات تبرايت تبرنامهت تهات تفراهمت تآوردت تكهت تصفحهت تنمايشت تشمات ترات تبهت تميزان‬ ‫كارآمدتري كنترل تكند‪ .‬بنابراين ممكن است چيزي شبيه تبهت ‪ TERM = a dm3‬رات به فايل‬ ‫‪ profile‬خودت تاضافهت تنمائيد‪ .‬همچنينت تاينت تامكانت توجودت تداردت تكهت تازت تمتغيرهات تبرايت تاختصار‬ ‫نويسي استفاده شود‪ .‬اگر مكررًا به برخي از دايركتوريها با نامهاي طولني مراجعه داشته‬


‫محیط برنامه سازی لینوکس‬

‫‪40/322‬‬

‫باشيد‪ ،‬اين امر شايسته است كه سطري همچون‬ ‫‪d= /harribly / lony / dinectory / name‬‬ ‫به ‪ profile‬خود اضافه نمائید‪ ،‬بنابراين مي‌توانید موردی شبیه ‪ cd $ d $‬را داشته باشید‪ .‬متغیرهای شخصي همچون ‪ d‬به منظور‬

‫متمايز نمودن آنها از مواردی که با خود ‪ Shell‬مورد استفاده قرار مي‌گیرند همچون ‪ ، PATH‬به صورت قراردادی با حروف کوچك‬

‫نوشته مي‌شوند‪ .‬نهايتا ً ‪ ،‬لزم است به ‪ Shell‬اعلم کنید که در نظر داريد از متغیرها در ديگر برنامه ها استفاده کنید‪ ،‬اين عمل با فرمان‬ ‫‪ expart‬انجام مي پذيرد‪ ،‬که در مورد اين موضوع در فصل ‪ 3‬بحث خواهیم کرد‪.‬‬

‫‪Exprot MAIL PATH TERM‬‬ ‫به منظور خلصه نمودن‪ ،‬در اين مرحله فايل ‪ ، profile‬معمولي وجود دارد که شبیه به اين مورد است‪:‬‬ ‫‪$ cat . profile‬‬ ‫‪STLy erase ∧h - Tabs‬‬ ‫‪MAIL = /usr/ spool/ mail / you‬‬ ‫‪PATH= $ HOME /bin : /bin: / usr/ bin:/usr/ games‬‬ ‫‪B=$ HOME / book‬‬ ‫‪Export MAIL PATH TERM b‬‬ ‫‪Date‬‬ ‫‪Who / WC-1‬‬ ‫‪$‬‬ ‫به هیچ وجه ما خدماتي را که ‪ Shell‬فراهم آورده است را ناديده نمي‌گیريم‪ .‬يکي از مفیدترين خدمات اين است که شما مي‌توانید‬ ‫فرمانهای شخصي خودتان را به وسیله بسته بندی فرمانهای موجود در يك فايل به منظور پردازش شدن بوسیله ‪ shell‬ايجاد کنید‪ .‬اين‬

‫نکته قابل توجه است که تا چه اندازه اين امر مي‌تواند به وسیله اين مکانیسم ساده به نتیجه برسد‪ .‬بحث ما در اين مورد از فصل ‪3‬‬

‫شروع مي‌شود‪.‬‬

‫‪5‬ت ‪ 1‬مابقي‪ ‬اطلاعات‪ ‬سيستم‪ ‬یونيکس‬ ‫نکات بیشتری در مورد سیستم يونیکس در مقايسه با آنچه که ما در اين فصل ارائه کرديم وجود دارد‪ ،‬اما اطلعات بیشتر در اين کل اين‬ ‫کتاب مطرح شده است‪ .‬اکنون‪ ،‬بايد در مورد اين سیستم احساس راحتي کرده باشید به ويژه در مورد کتاب راهنما‪ .‬زمانیکه شما سوالت‬

‫خاصي در مورد زمان و چگونگي استفادة فرمانها داريد‪ ،‬کتاب راهنما جايگاه بررسي پاسخ شماست‪ .‬همچنین اين نکته مفید و باارزشي‬

‫است که که گاهي در کتاب راهنما جستجو صورت گیرد‪ ،‬به اين منظور که دانش شما از آشنايي با فرمانها و کشف اطلعات جديد‪ ،‬به‬

‫روز شود‪ .‬کتاب راهنما بسیاری از برنامه‌هايي که ما نبايد توضیح دهیم و عبارتند از گردآورندگاني برای زبانهايي همچون ‪FORTRAN‬‬

‫‪ ، 71‬برنامه های ماشین حساب همچون ‪ )bc)1( ، cu)1‬و ‪ )uncp)1‬برای ارتباطات بین ماشیني‪ ،‬بسته‌بنديهای طرحها‪ ،‬برنامه‌های آماری‬ ‫و رمزهايي همچون ‪ ، )units)1‬را تشريح مي‌کند‪ .‬همانگونه که پیش از اين نیز گفته شد اين کتاب جايگزين برای راهنما نمي‌باشد بلکه‬

‫آن را تکمیل مي‌کند‪ .‬در فصلهايي که در پیش است ‪ ،‬ما به بخشها و برنامه‌های سیستم يونیکس اشاره خواهیم کرد که اين فرايند از‬

‫اطلعاتي در راهنما آغاز مي‌شود اما رشته‌هايي را پي گیری مي‌کند که پیوند دهندة اجزاء و بخشهای کتاب است ‪ .‬اگرچه ارتباطات‬ ‫برنامه‌ها هرگز در کتاب راهنما به وضوح مشخص نشده است اما آنها اصل محیط برنامه سازی يونیکس را تشکیل مي‌دهند‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪41/322‬‬

‫تاريخچه و نكات مربوط به تأليفات‬ ‫مقالة اصلي يونیکس توسطـ ‪ K.L.thompson , D.M.Ritchie‬تهیه شده است‪ .‬اصل سیستم اشتراك زماني يونیکس تحت عنوان‬

‫ارتباطاتـ ‪ ACM‬در جولی سالـ ‪ 1974‬تهیه شد و درـ ‪ CACM‬و در ماه ژانويهـ ‪ 1983‬دوباره چاپ شد‪( .‬صفحهـ ‪ 89‬چاپ جديد‬ ‫موضوع بحث ماه مارس سال ‪ 1983‬قرار گرفت)‪ .‬اين بررسي کلي از سیستم برای افراد علقه مند به سیستم عامل جهت خواندن توسط‬

‫هر فردی که برنامه نويس است‪ ،‬ارزشمند است‪ .‬مجله تکنیکي سیستم ‪ )Bell )BSTJ‬که موضوع ويژه‌ای پیرامون سیستم يونیکس است‬

‫(جولی ‪ )1978‬حاوی مقالت بسیاری است که تشريح کنند تحول بعدی است و برخي از موضوعات گذشته شامل مقالت جديد‬ ‫مجله ‪ CA CM‬است که توسط ‪ Ritchie‬و ‪ thompson‬تهیه شده است‪ .‬دومین موضوع خاص ‪ RSTJ‬حاوی مقالت جديد سیستم‬

‫يونیکس است که که به منظور چاپ شدن در سال ‪ 1984‬طرح ريزی شده است‪ .‬محیط برنامة يونیکس که توسط ‪J.R.Mashey ,‬‬

‫‪ B.W.kernighan‬تنظیم شده (مجله کامپیوتر ‪ . IEEE‬ماه آوريل سال ‪ )1981‬جهت انتقال خصوصیات اصلي سیستم به برنامه سازان‬ ‫تلش مي‌کند‪ .‬راهنمای برنامه ساز يونیکس در هر نوع برای سیستم شما‪ ،‬فهرست فرمانها‪ ،‬سیستم ها عادی و مشترك‪ ،‬قالب بندی فايل‬ ‫و روندهای حفظ و نگهداری مناسب هستند‪ .‬شما بدون اين سیستم برای مدت طولن نمي‌توانید دوام بیاوريد اگرچه شما احتما ًل تنها به‬

‫خواندن بخشهای از جلد ‪ 1‬تا زمان شروع برنامه‌سازی نیازمند باشید‪ .‬جلد ‪ 1‬چاپ هفتم کتاب راهنما توسط ‪ HolT ، Rinehart‬و‬

‫‪ winston‬به چاپ رسید‪ .‬جلد ‪ 2‬راهنمای برنامه ساز يونیکس تحت عنوان سندی برای استفاده از سیستم اشتراك زماني ‌يونیکس نام‬ ‫دارد و حاوی نکات آموزشي و مرجع برای اکثر فرمانها مي‌باشد‪ .‬به ويژه اين کتاب نکات مقدماتي برنامه‌ها و ابزارهای توسعه برنامه‌ها‬

‫را به تفصیل بیان مي‌کند‪ .‬ممکن است شما بخواهید اغلب اين مطالب را هرچند وقت مطالعه کنید‪ .‬کتاب مقدماتي يونیکس که توسط‬

‫‪ Aun‬و ‪ Nico Lomuto )1983‬ـ ‪ Hall‬ـ ‪ )prentice‬تهیه شده است‪ ،‬مقدمة مناسبي برای افراد مبتندی بي‌‌تجربه به ويژه افرادی که‬ ‫برنامه نويس نیستند‪ ،‬به شمار مي‌رود‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪42/322‬‬

‫فصل ‪ : 2‬سیستم فایل‬ ‫همه چیز در سیستم يونیکس به صورت يك فايل است‪ .‬اين سیستم بسیار ساده‌تر از آن است که شما فکر مي‌کنید‪ .‬زمانیکه اولین نسخه‬

‫اين سیستم طراحي مي‌شد‪ ،‬قبل از آن که نامي داشته باشد‪ ،‬بحثها بروی سیستم فايل متمرکز شد که برای استفاده‪ ،‬تمیز و ساده باشد‪.‬‬

‫سیستم فايل مرکز موفقیت و سادگي سیستم يونیکس است‪ .‬اين سیستم يکي از بهترين مثال‌های فلسفه «ساده‌تر کنید» است؛ که نشان‬ ‫دهنده توان عملکرد پیاده سازی چند ايده درست انتخاب شده مي‌باشد‪.‬‬

‫برای راحتر صحبت کردن در مورد دستورات و روابط آنها نیاز به پیش زمینه مناسبي از ساختار و عملکرد بیروني فايل سیستم داريم‪.‬‬

‫اين فصل بسیاری از جزئیات استفاده از سیستم فايل را در بر دارد‪ -‬فايل چیست‪ ،‬چگونه بازنمايي مي‌شود‪ ،‬شاخه‌ها و سلسله مراتب‬ ‫فايل سیستم‪ ،‬مجوزها‪(inode ،‬رکورد داخلي سیستم فايل) و فايل‌های دستگاه جانبي‪.‬‬

‫چون بسیاری از کاربردهای يونیکس منجر به دستکاری فايل‌هامي‌شود‪ ،‬فرمان‌ها و دستورات زيادی برای فايل بررسي و تنظیم فايل‌ها‬ ‫دارد؛ در اين فصل به برسي پرکاربردترين آنها پرداخته مي‌شود‪.‬‬

‫مباني فايل‌ها‬ ‫يك فايل رشته‌ای از بايتها است‪( .‬بايت تکه کوچکي از اطلعات است‪ ،‬که عموماً هشت بیت طول دارد‪ .‬يك بايت را مي‌توان معادل با‬

‫يك کاراکتر دانست‪ ).‬سیستم هیچ ساختاری بر روی فايل و هیچ معنايي برای محتوای آن در نظر نمي‌گیرد؛ مفهوم بايت‌ها فقط به‬

‫برنامه‌ايي که فايل را تفسیر مي‌کند‪ ،‬بستگي دارد‪ .‬علوه بر اين همانطور که خواهید ديد‪ ،‬اين موضوع نه تنها در مورد فايل‌های ذخیره‬

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

‫معادل رشته‌ای از بايت‌ها مي‌باشند‪.‬‬

‫بهترين راه درك فايل بازی کردن با آن‌ها است‪ ،‬بنابراين با ايجاد يك فايل کوچك شروع مي‌کنیم‪:‬‬

‫‪$ed‬‬ ‫‪a‬‬ ‫‪now is the time‬‬ ‫‪for all good people‬‬ ‫‪.‬‬ ‫‪w junk‬‬ ‫‪36‬‬ ‫‪q‬‬ ‫‪$ ls -l junk‬‬ ‫‪-rw-rw-r-- 1 mahdi mahdi 36 Jul 4 11:21 junk‬‬ ‫‪$‬‬ ‫‪ Junk‬فايلي ‪ 36‬بايتي است‪ 36( .‬کاراکتری که شما هنگام ايجاد فايل تايپ کرده‌ايد؛ البته به جز اصلحات اشتباهات تايپي )‪ .‬برای ديدن‬ ‫فايل‪،‬‬

‫‪$ cat junk‬‬ ‫‪now is the time‬‬ ‫‪for all good people‬‬ ‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪43/322‬‬

‫دستور ‪ cat‬نشان مي‌دهد که محتوای فايل چیست‪ .‬دستور ‪ 2od‬تمام بايت‌های فايل را بصورتي قابل رؤيت باز نمايي مي‌کند‪:‬‬

‫‪$ od -c junk‬‬ ‫‪0000000 n o w‬‬ ‫‪i s‬‬ ‫‪t h e‬‬ ‫‪t i m e \n‬‬ ‫‪0000020 f o r‬‬ ‫‪a l l‬‬ ‫‪g o o d‬‬ ‫‪p e o‬‬ ‫‪0000040 p l e \n‬‬ ‫‪0000044‬‬ ‫‪$‬‬ ‫گزينه ‪ c‬به معنی تفسير(نمایش) بایتها به صورت کارکتری است‪ .‬انتخاب گزينه ‪ ،b‬بايت‌ها را‬ ‫به اكتال (‪ )octal‬نيز نشان مي‌دهد‪:‬‬ ‫‪od -cb junk $‬‬

‫‪0000000 n o w‬‬ ‫‪i s‬‬ ‫‪t h e‬‬ ‫‪t i m e \n‬‬ ‫‪156 157 167 040 151 163 040 164 150 145 040 164 151 155 145 012‬‬ ‫‪0000020 f o r‬‬ ‫‪a l l‬‬ ‫‪g o o d‬‬ ‫‪p e o‬‬ ‫‪146 157 162 040 141 154 154 040 147 157 157 144 040 160 145 157‬‬ ‫‪0000040 p l e \n‬‬ ‫‪160 154 145 012‬‬ ‫‪0000044‬‬ ‫‪$‬‬ ‫اعداد هفت رقمي که در پائین سمت چپ نمايش داده مي‌شوند‪ ،‬شماره ترتیب کاراکتر در فايل برای اولین کارکتر نمايش داده شده در‬

‫آن خط است‪.‬‬

‫به هر ترتیب‪ ،‬تأکید بر روی شماره‌های اکتال‪ ،‬يك نظريه پابرجا از ‪ PDP –11‬است‪ ،‬که در آن اکتال نمادگذاری پیشنهادی بوده است‪.‬‬ ‫مبنای ‪ 16‬سازگاری بیشتری با ساير سخت افزارها دارد؛ گزينه ‪ x‬به ‪ od‬مي‌گويد که اطلعات به صورت هگز چاپ کند‪.‬‬

‫توجه داشته باشید که در هر خط با يك کاراکتر ‪ 012‬اکتال پايان مي‌يابد‪ .‬اين کاراکتر ‪( newwline‬خط جديد) اسکي است؛ چیزی که‬

‫سیستم در اثر فشار کلید ‪ enter‬دريافت مي‌کند‪ .‬بنابر يك عرف وام گرفته شده از زبان ‪ C‬کارکتر خط جديد با ‪ \n‬نمايش داده مي‌شود‪.‬‬

‫اما بايد توجه داشت که اين نوع نمايش قراردادی برای برنامه‌هايي شبیه ‪ od‬است تا راحتتر بتوان آن را خواند؛ در سیستم يك بايت با‬ ‫مقدار ‪ 012‬ذخیره مي‌گردد‪.‬‬

‫کارکتر ‪ newline‬رايج‌ترين مثال كاراكترهای خاص است‪ .‬سایر كاراكترها با بعضی از عمليات‬ ‫كنترلی پايانه مرتبط مي‌باشند‪ ،‬كه شامل ‪( backspace‬پس برد به عقب) (با مقدار اكتال ‪010‬‬ ‫‪ ،‬چاپ شده به صورت \‪ )b‬کارکتر ‪ )\tab)011،t‬و كاراكتر سر خط‪ )\r ،015( 3‬مي‌باشد‪.‬‬ ‫نکته بسیار مهم درك و تفکیك نحوه ذخیره سازی کارکترها در فايل و چگونگي تفسیر آنها در موقعیت‌های مختلف است‪ .‬برای مثال‬ ‫وقتي شما ‪ backspace‬را روی صفحه کلید فشار مي‌دهید هسته آن را به معنای حذف کاراکتر قبلي تفسیر مي‌کند ‪ .‬کاراکتر قبلي و‬

‫‪ backspace‬ناپديد مي‌شوند‪ ،‬اما ‪ backspace‬به پايانه شما انعکاس داده مي‌شود تا مکان نما يك موقعیت به عقب برگردد‪.‬‬

‫اگر شما رشته ←\ را تايپ كنيد (\ و به دنبال آن یک ‪ )backspace‬به هر حال هسته تفسير‬ ‫معمول خود از ‪ backspace‬را دارد؛ بنابراين ت \ حذف مي‌شود و بايت ‪ 010‬از فايل شما محو‬ ‫مي‌شود‪ .‬انعکاس ‪ backspace‬بروي پايانه مكان نما را یک خانه به عقب برده و برروی \ قرار‬ ‫می‌دهد‪.‬‬ ‫چاپ فايلي که شامل ‪ backspace‬است؛ موجب مي‌شود که ‪ backspace‬بدون تفسیر به ترمینال منعکس شود و در نتیجه مکان نما يك‬ ‫‪octal dump2‬‬ ‫‪Carriage return3‬‬


‫محیط برنامه سازی لینوکس‬

‫‪44/322‬‬

‫خانه به عقب برگردد‪ .‬در صورت استفاده از ‪ od‬برای نمايش فايلي که دارای ‪ backspace‬است‪ ،‬اين کارکتر به صورت ‪ 010‬در صورت‬

‫استفاده از گزينه ‪ d‬و به صورت ‪ \b‬در صورت استفاده از گزينه ‪ c‬نمايش داده خواهد شد‪.‬‬

‫داستان ‪ tab‬نیز به همین صورت است‪ :‬در هنگام تايپ يك ‪ ،tab‬اين کارکتر به پايانه منعکس شده و همچنین به برنامه‌ای که ورودی را‬

‫م‌خواند فرستاده مي‌شود‪ .‬در خروجي‪ tab ،‬به سادگي به پايانه فرستاده مي‌شود تا در آنجا تفسیر شود‪ .‬البته در تفسیر ‪ tab‬برای نمايش‬

‫تفاوتهايي وجود دارد‪ .‬امکان تنظیم مشخصات سیستم برای نمايش اين کارکتر به صورت‌های مختلف توسط هسته پیش‌بیني شده است‪.‬‬

‫بطور معمول هر کارکتر ‪ tab‬با تعدادی فضای خالي جايگزين مي‌شود تا مکان نما به سر خانه جدولي بعدی برود‪ .‬سر خانه‌های جدول‬

‫برروی ستون‌های ‪ … ،25 ، 17 ، 9‬قرار دارند‪ .‬دستور ‪ stty -tabs‬منجر مي‌شود که از اين به بعد ‪ tab‬با تعدادی فضای خالي جايگزين‬

‫شود‪ .‬برای کسب اطلعات دقیقتر به راهنمای ‪ )stty)1‬مراجعه کنید‪.‬‬

‫رفتار ‪ enter‬قیاسي است‪ .‬هسته ‪ enter‬را به صورت يك کاراکتر سر خط و يك ‪ newline‬منعکس مي‌کند؛ اما تنها ‪ newline‬را در‬ ‫ورودی ذخیره مي‌کند‪ .‬برای خروجي نیز ‪ newline‬به آن دو کارکتر بسط داده مي‌شود‪.‬‬

‫روش يونیکس برای نمايش اطلعات کنترلي به خصوص در مورد کاربرد ‪ newline‬به منظور اعلم پايان خط متعارف نیست‪ .‬در‬

‫بعضي از سیستم‌ها به جای قراردادن هر رکرد در يك خط تعداد کارکترهای رکورد را نیز نگهداری مي‌کنند (البته بدون هیچ علمت پايان‬ ‫خط يا رکوردی)‪.‬‬

‫بقیه سیستم‌ها پايان هر خط را با کاراکتر سر خط و ‪ newline‬نمايش مي‌دهند؛‪ .‬زيرا اين کارکترها برای خیلي از پايانه‌ها ضروری‬

‫است‪( .‬واژه ‪ linefeed‬معادل اين دو کارکتر است که اين معادل غالبا «‪ »CRLF‬خوانده مي‌شود که تقريباً قابل تلفظ است‪).‬‬

‫سیستم يونیکس هرگز دارای رکورد‪ ،‬شمارنده رکورد و يا هر اطلعي که شما يا برنامه در فايل قرار نداده باشید‪ ،‬نمي‌باشد‪ .‬يك‬ ‫‪ newline‬زمان انعکاس به پايانه به کاراکتر سر خط و ‪ newline‬بسط داده مي‌شود؛ اما برنامه‌ها نیاز دارند که تنها با کاراکتر ‪newline‬‬

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

‫تا زمانیکه انتهای خط با کاراکترـ ‪ newline‬علمت‌گذاری مي‌شود ممکن است انتظار داشته باشید که فايل به وسیله کاراکتر خاص‬ ‫ديگری خاتمه پیدا کند‪ .‬نماد (‪ )\e‬را برای انتهای فايل در نظر بگیريد‪ .‬در خروجي ‪ od‬کاراکتر خاصي در انتهای فايل نمايش داده‬

‫نمي‌شود؛ بلکه تنها نمايش متوقف مي‌شود‪ .‬بجای استفاده از کدی خاص‪ ،‬سیستم با اعلم عدم وجود داده بیشتر در فايل خاتمه يافتن‬

‫فايل را مشخص مي‌کند‪ .‬هسته طول فايل را نگهداری مي‌کند‪ ،‬بنابراين برنامه پس از پردازش تمام بايتهای فايل با پايان فايل مواجه‬ ‫مي‌شود‪.‬‬

‫برنامه با يك فراخواني سیستمي(روالي از هسته) که ‪ read‬نام دارد داده‌ّای درون فايل را بازيابي مي‌کند‪ .‬هر بار که ‪ read‬فرا خوانده‬ ‫مي‌شود‪ ،‬بخش بعدی فايل مثل خط بعدی که روی پايانه تايپ شده است‪ ،‬را بر مي‌گرداند‪ .‬علوه بر اين ‪ read‬مي‌گويد که چه تعداد‬

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

‫يك مقدار خاص نبايد نمايش داد‪ ،‬زيرا همانطور که قبل بیان شد مفهوم بايت‌ها به نحوه تفسیر بايت‌ها بستگي دارد‪ .‬اما همه فايلها بايد‬

‫به پايان برسند و چون همه فايلها بايد به کمك ‪ read‬خوانده شوند‪ ،‬برگشت صفر يك راه مستقل از تفسیر برای نمايش پايان فايل است‬


‫محیط برنامه سازی لینوکس‬

‫‪45/322‬‬

‫بدون اينکه نیاز به معرفي يك کاراکتر جديد برای اينکار باشد‪.‬‬

‫وقتي که يك برنامه از پايانه شما مي‌خواند هر خط ورودی وقتي که کارکتر ‪ newline‬تايپ شده بوسیله هسته به برنامه داده مي‌شود‪.‬‬

‫بنابراين وقتي که ي ك اشتباه تايپي مرتکب مي‌شويد مي‌توانید برگرديد و آن ر ا تصحیح کنید‪ .‬البته اگر اشتباه ر ا قب ل ا ز فشار‬

‫‪Enter‬تشخیص دهید‪ .‬بعد از آن خط توسط سیستم خوانده شده و شما نمي‌توانید آن را اصلح کنید‪.‬‬

‫با استفاده از برنامه ‪ cat‬مي‌توان ورود اطلعات به صورت هر بار يك خط را مشاهده کرد‪ .‬در بعضي از سیستمهای قديمي ‪ cat‬به طور‬

‫معمول برای افزايش کارايي خروجي خود را بافر مي‌کند‪ .‬برای رفع اين مشکل از گزينه ‪ u‬مي‌توان استفاده کرد‪:‬‬

‫‪$cat -u‬‬ ‫‪123‬‬ ‫‪123‬‬ ‫‪456‬‬ ‫‪456‬‬ ‫‪789‬‬ ‫‪789‬‬ ‫‪ctl-d‬‬ ‫‪$‬‬ ‫زمانیکه ‪ return‬را فشار دهید ‪ cat‬خط را دريافت مي‌کند؛ بدون بافر کردن اطلعات بلفاصله پس از دريافت آن را چاپ مي‌کند‪.‬‬

‫حال موارد متفاوت را امتحان كنيد؛ تعدادي كاراكتر و بعد از آن يك ‪ ctl-d‬بجای ‪ Enter‬تايپ كنيد‪:‬‬ ‫‪$ cat -u‬‬ ‫‪123ctl-d123‬‬ ‫‪ Cat‬کاراکترها را بلفاصله چاپ مي‌کند‪ .‬تايپ ‪ ctl-d‬مي‌گويد «کاراکترها بلفاصله بفرست؛ من برای برنامه‌ای که از پايانه مي‌خواند‬ ‫تايپ کرده‌ام»‪.‬‬

‫برعکس ‪ Enter‬خود ‪ ctl-d‬به برنامه فرستاده نمي‌شود‪ .‬حال دومين ‪ ctl-d‬را بدون كاراكترهاي‬ ‫ديگر تايپ كنيد‪:‬‬

‫‪$ cat -u‬‬ ‫‪123ctl-d123ctl-d$‬‬ ‫شل با يك پیامواره پاسخ مي‌دهد؛ زيرا ‪ Cat‬هیچ کاراکتری را نمي‌خواند‪ ،‬قطعا اين به معني پايان فايل است در نتیجه متوقف مي‌شود‪.‬‬ ‫‪ ctl-d‬هر چیزی را که شما تايپ کرده‌ايد به برنامه‌ای که از پايانه مي‌خواند مي‌فرستد‪ .‬اگر شما چیزی تايپ نکرده باشید‪ ،‬بنابراين برنامه‬

‫هیچ کاراکتری را نمي‌خواند و اين چیزی شبیه به انتهای فايل است‪ .‬به همین دلیل تايپ کردن ‪ ctl-d‬شما را از سیستم خارج مي‌کند‪،‬‬ ‫زيرا شل ورودی ديگری نمي‌بیند‪ .‬البته ‪ ctl-d‬برای مشخص کردن انتهای فايل استفاده مي‌شود‪ .‬البته عملکرد عمومي بیشتری دارد‪.‬‬

‫در فایل چه چیزی هست؟‬ ‫قالب بندی فايل به وسیله برنامه‌هايي که از آن استفاده مي‌کنید معین مي‌شود؛ انواع فايل‌ها شديدا متنوعند‪ ،‬شايد به خاطر اينکه برنامه‌ها‬

‫متنوعي وجود دارد‪ .‬ولي تا زمانیکه نوع فايل توسط فايل سیستم مشخص نشود‪ ،‬هسته نمي‌تواند نوع فايل را مشخص کند؛ زيرا در مورد‬

‫آن چیزی نمي‌داند‪ .‬دستور ‪ file‬يك حدس مناسب ارائه مي‌کند‪:‬‬

‫‪$ file /bin /bin/ed /usr/share/man/man1/ed.1.gz‬‬ ‫‪/bin:‬‬ ‫‪directory‬‬ ‫‪/bin/ed:‬‬ ‫‪ELF 32-bit LSB executable, Intel 80386, version 1 )SYSV(, for GNU/Linux‬‬


‫محیط برنامه سازی لینوکس‬

‫‪46/322‬‬

‫‪2.2.5, dynamically linked )uses shared libs(, stripped /usr/share/man/man1/ed.1.gz: gzip compressed‬‬ ‫‪data, from Unix, max compression‬‬ ‫‪$‬‬ ‫اينها سه فايل نسبتا نوعي هستند که همه به ويراستار ‪ ed‬مرتبطند‪ :‬شاخه‌ای که برنامه در آن موجود است‪ ،‬باينری يا برنامه قابل اجرا و‬

‫صفحه راهنمای برنامه‪.‬‬

‫برای مشخص کردن نوع‪ file ،‬توجهي به نام ندارد‪ ،‬زيرا عرفه نامگذاری‪ ،‬تنها يك قرارداد و کامل غیر حقیقي است‪ .‬برای مثال پسوند ‪.c‬‬

‫برای کدهای زبان ‪ C‬در نظر گرفته شده است ولي هیچ دلیلي وجود ندارد که شما از فايلي به نام ‪ a.c‬با محتوايي دلخواه اجتناب کنید‪.‬‬

‫در عوض ‪ ،file‬چند صد بايت اول فايل را مي‌خواند و به دنبال سر نخهايي برای تعیین نوع فايل مي‌گردد‪( .‬همانطور که قبل بیان کرديم‬

‫در بعضي مواقع مثل در مورد شاخه‌ها ‪ file‬مي‌تواند از سیستم سئوال کند؛ البته حتي در همین موارد هم فايل با خواندن اول شاخه‬

‫مي‌تواند آن را تشخیص دهد‪).‬‬

‫بعضي مواقع سرنخ‌ها مشخص‌اند‪ ،‬يك برنامه قابل اجرا توسط يك شماره جادويي در ابتدای خود علمت‌گذاری مي‌شود‪ od .‬بدون هیچ‬ ‫گزينه‌ای فايل را به صورت ‪ 16‬بیتي يا ‪ 2‬بايتي نمايش داده و شماره‌ جادوئي را قابل رويت مي‌کند‪:‬‬

‫‪$ od /bin/ed‬‬ ‫‪0000000 042577 043114 000401 000001 000000 000000 000000 000000‬‬ ‫‪0000020 000002 000003 000001 000000 107140 004004 000064 000000‬‬ ‫‪0000040 127244 000000 000000 000000 000064 000040 000007 000050‬‬ ‫عدد ‪ ،042577‬نشانگر وجود برنامه‌ای قابل اجراست‪ .‬يك کد اجرايي ممکن است توسط تعدادی پردازه همزمان اجرا شود‪ .‬الگوی بیتي‬ ‫که با ‪ 042577‬نشان داده مي‌شود‪ ،‬يك متن ‪ ASCll‬نیست‪ .‬و اين مقدار نمي‌تواند توسط برنامه‌ای شبیه ويراستار ساخته شود‪ .‬اما شما‬ ‫مي‌توانید فايلي توسط برنامه‌های خاص خود بسازيد‪ ،‬و سیستم فکر کند که آن يك برنامه اجرايي است‪.‬‬

‫برای فايل‌های متني‪ ،‬سرنخها ممکن است عمیق‌تر باشند‪ .‬بنابراين ‪ file‬به دنبال واژه‌ای شبیه ‪ #include‬مي‌گردد تا مشخص کند فايل‬

‫مورد نظر کد ‪ C‬است‪.‬‬

‫شما ممکن است از خود بپرسید که چرا سیستم نوع فايل را با دقت در نظر نمي‌گیرد‪ .‬برای مثال ‪ sort‬فايل ‪ bin/ed/‬را بعنوان ورودی‬ ‫نگیرد‪ .‬يکي از دليلش خودداری در جلوگیری از بعضي از محاسبات مفید است‪.‬‬

‫شاخه‌ها و اسامي فايلها‬

‫همه فايل‌های شما‪ ،‬اسامي واضح و غیرمبهمي دارند که با ‪ home/you/‬شروع مي‌شوند‪ .‬اما اگر ‪ junk‬تنها فايل شما باشد و ‪ ls‬را اجرا‬ ‫کنید به صورت ‪ usr / you / junk /‬تايپ نمي‌شود‪ .‬نام فايل بدون هیچ پیشوندی اينگونه تايپ مي گردد‪.‬‬

‫‪IS‬‬ ‫‪junk‬‬

‫‪$‬‬

‫‪$‬‬ ‫به همین دلیل برنامه در جريان که يك فرايند محسوب مي‌شود‪ ،‬يك دايرکتری جاری دارد‪ .‬و تمامي نام فايل‌ها به صورت صنفي ايگونه‬ ‫فرض مي‌شود که با نام آن‪ ،‬دايرکتری آغاز شده است‪ .‬مگر اينکه آنها مستقیماً با اسلش آغاز شوند‪ .‬بنابراين راه‌يابي به سیستم عامل و ‪IS‬‬ ‫يك دايرکتری جاری دارد‪ .‬فرمان « کارکرد دايرکتری را چاپ کن» دايرکتری جاری را شناسايي مي‌ند‪.‬‬

‫‪pwd‬‬ ‫‪/ usr / you‬‬

‫‪$‬‬

‫‪$‬‬ ‫راهنمای جاری (دايرکتری جاری) مشخصه‌ای از يك فرايند است نه از يك شخص يا برنامه‪ .‬عموما ً همه دايرکتری ورود به سیستم‬


‫محیط برنامه سازی لینوکس‬

‫‪47/322‬‬

‫عامل را دارند و فرايندها دارای دايرکتری جاری هستند‪ .‬اگر فرايند‪ ،‬يك فرايند مولد ايجاد کند‪ ،‬اين مولد‪ ،‬دايرکتری جاری والد خود را‬

‫با تمامي مشخصاتش به دست مي‌آوردـ ‪ :‬البته اگر مولد يك راهنمای جديدـ (دايرکتری جديد) تغییر يافت تأثیر بر روی والد خود‬

‫نمي‌گذارد‪ .‬دايرکتری جاری به همان شکل باقي مي‌ماند و به چگونگي مولد اهمیتي نمي‌دهد‪.‬‬

‫تصويری از يك راهنمای جاری (دايرکتری جاری) مطمئناً يك نمادگزاری قرارداديست‪ .‬زيرا مي‌تواند بسیاری از نوع سازی‌ها را ذخیره‬

‫سازد‪ .‬اما هدف واقعي و اصلي آن سازماني و از پیش‌برنامه ريزی شده است‪ .‬فايل‌های مرتبط در دايرکتری‌های يکسان‪ ،‬به يکیگر تعلق‬

‫دارند‪ usr / .‬معمول دايرکتری باليي از يك کاربر سیستم فايل است ‪ usr( .‬علمت اختصاری ‪ user‬است) وقتي که شما وارد سیستم‬

‫عامل مي‌شويد ‪ usr / you /‬دايرکتری ورودی و دايرکتری جاری شما هستند‪:‬‬

‫‪ usre / src /‬شامل منبعي از برنامه‌های سیستم است‪ usr / src / smd / .‬شامل منبعي از فرمان يونیکس است‪usr / src / smd / sh / .‬‬

‫شامل فايل اصلي برای شل است و غیره‪ .‬وقتي که شما دست به يك پروژه جديد مي‌زنید و يا وقتي يك سری فايل مرتبط داريد و يك‬ ‫سری دستورالعمل بیان مي‌کنید مي‌توانید با ‪ mkdir‬يك دايرکتری جديد بسازيد و آن را در فايل‌ها قرار دهید‪.‬‬

‫‪$ pwd‬‬ ‫‪/ usr / you‬‬ ‫‪$ mk dir recipes‬‬ ‫‪$ cd recifes‬‬ ‫‪$ pwd‬‬ ‫‪/ usr / you / recipes‬‬ ‫‪$ mkdir pie cookie‬‬ ‫‪$ ed pie / aplole‬‬ ‫………‬ ‫‪$ ed cookier / choc. Chip‬‬ ‫………‬ ‫‪$‬‬

‫توجه داشته باشید که رجوع کردن به يك دايرکتری فرعي بسیار ساده است‪ pie/apple .‬يك مفهوم کامل واضحي دارد‪ .‬دستورالعمل‬ ‫‪ apple pie‬در دايرکتری بدين شکل است‪.‬‬

‫‪/ recipes / apple pie‬‬ ‫اما قرار گرفتن تمامي ‪ pies‬با هم سازمن يافته‌تر به نظر مي‌رسد‪ .‬برای مثال دستورالعمل ‪ crust‬به جای کپي گرفتن از آن در هر سیستم‬ ‫‪ pie‬به صورت ‪ recipes / pie‬اجرا شود‪.‬‬

‫گرچه سیستم فايل يك ابزار سازمان يافته قدرتمند است شما ممکن است فراموش کنید که فايل را کجا قرار داده‌ايد و يا به چه فايلي‬

‫دست يافته‌ايد‪ .‬يك راه حل واضح و روشن برای يافتن فايل يك يا دو فرمان جستجو کردن در میان دايرکتری‌هاست‪ .‬زمان ‪ IS‬برای‬

‫يافتن فايل بسیار مؤثر است ‪ ،‬بدون اينکه به دايرکتری فرعي مراجعه شود‪.‬‬

‫‪$ cd‬‬ ‫‪$ Is‬‬ ‫‪junk‬‬ ‫‪recipes‬‬ ‫* ‪$ file‬‬ ‫‪jund ascit text‬‬


‫محیط برنامه سازی لینوکس‬

‫‪48/322‬‬

‫‪recips :‬‬ ‫‪directory‬‬ ‫‪$ IS re cipes‬‬ ‫‪cookie‬‬ ‫‪pie‬‬ ‫‪$ IS recipes / Pie‬‬ ‫‪apple‬‬ ‫‪crust‬‬ ‫\‪$‬‬ ‫تصويري از يك سيستم فایل در زير نشان داده شده است‪.‬‬ ‫‪usr /you /‬‬ ‫‪recipics‬‬ ‫‪cookie‬‬ ‫‪choc.ship‬‬

‫‪junk‬‬ ‫‪pie‬‬

‫‪crust‬‬

‫‪apple‬‬

‫فرمان ‪( du‬کاربرد ديسك) نوشته شده است تا بیان کند چه مقدار از فضای ديسك توسط فايل‌های داخل دايرکتری اشغال شده‪ ،‬که‬

‫شامل تمامي فايل‌های فرعي نیز مي‌باشد‪.‬‬

‫‪$ du – a‬‬ ‫‪2‬‬ ‫‪. / recipes / pie / apple‬‬ ‫‪3‬‬ ‫‪. / recipes / pie / crust‬‬ ‫‪6‬‬ ‫‪. / recipes / pie‬‬ ‫‪3‬‬ ‫‪. / recipes / cookie/ choc.chip‬‬ ‫‪4‬‬ ‫‪. / recipes / cookie‬‬ ‫‪11‬‬ ‫‪. / recipes /‬‬ ‫‪1‬‬ ‫‪. / junk‬‬ ‫‪13‬‬ ‫‪.‬‬ ‫‪$‬‬ ‫نام فايل‌ها واضح و مشخص است‪ .‬اين اعداد شماره بلوك‌های ديسك ذخیره‌سازی به ازای هر فايل محسوب مي‌گذارند ـ تقريباً به ازای‬ ‫هر ‪ 1024‬يا ‪ 512‬بايت ـ اندازة هر دايرکتوری نشان مي‌دهد چند بلوك توسط فايل‌ها در دايرکتری و دايرکتری فرعي اشغال شده که‬

‫شامل دايرکتری نیز مي‌شود‪ Du .‬برای « ‪ »wll‬يك گزينه ‪ a‬دارد که باعث مي‌شود تمامي فايل‌ها در دايرکتری چاپ شود‪ .‬اگر يکي از‬ ‫آن‌ها دايرکتری‪ du ،‬را اينگونه پردازش مي‌کند‪.‬‬

‫خروجي ‪ dw – a‬مي‌تواند برای جستجوی فايل‌های ويژه مسیری به طرف ‪ grep‬ايجاد کند‪.‬‬

‫‪$ du – a / grep choc‬‬ ‫‪$‬‬ ‫‪. / recipes / cookie / choc. Chip‬‬ ‫‪$‬‬ ‫نگاهي دوباره به قسمت يك داشته باشید‪ .‬نام (’‪ )‘.‬مدخل دايرکتری مي‌باشد که به خود دايرکتری رجوع پیدا مي‌کند ودستیابي به‬


‫محیط برنامه سازی لینوکس‬

‫‪49/322‬‬

‫دايرکتری را بدون دانستن نام آن مجاز مي شمرد‪ Du .‬برای يافتن فايل به دايرکتری سری مي‌زند‪ ،‬اگر شما به او نگوئید کدام دايرکتری‬

‫او فرض را بر اين علمت (’‪ )‘.‬مي‌گذارد‪ .‬بنابراين ‪ junk‬و ‪ junk / .‬نام فايل‌های مشابهند‪.‬‬

‫علوه بر مشخصات بنیادی داخل هسته ‪ ،‬دايرکتری‌ها در سیستم فاعلي به عنوان فايل های معمولي قرار مي‌گیرند‪ .‬آن‌ها مي‌توانند به‬

‫عنوان فايل‌های معمولي نیز خوانده شوند‪ .‬به منظور حفظ اعتدال و فايل‌های کاربر‪ ،‬هسته کنترل همه اطلعات دايرکتری را در دست‬ ‫مي‌گیرد‪.‬‬

‫تايم نگاهي به بايت‌ها در راهنما مي‌اندازد ‪:‬‬

‫به نام فايل‌های پنهان شده در آنجا نگاهي کنید‪ .‬فرمت دايرکتری مخلوطي از دودوئي و داده های در متن است‪ .‬يك دايرکتری شامل‬

‫قسمت‌های ‪ 16‬بايتي مي‌باشند و ‪ 14‬بايت آخر که نام فايل‌ها را در بر دارند توسط ‪ ASCll Nul’s‬بسط داده مي‌شود‪( .‬که ارزش صفر‬ ‫دارد)‪ .‬و دو تای اولي بیان مي‌کند که سیستم اطلعات اداری را در کجای فايل قرار مي‌دهد‪ .‬ما بعداً به اين مطلب دوباره اشاره خواهیم‬

‫کرد‪ .‬هر دايرکتری با دو ورودی آغاز مي‌شود (“‪‘.’)“dot”( and‬‬

‫‘ ‪dot-dot”( ’.‬‬

‫دايرکتری ‪ ،‬ريشه (‪ )Root‬سیستم عامل خوانده مي‌شود‪ .‬هر فايلي در سیستم در دايرکتری ريشه و يا يکي از دايرکتری‌های فرعي آن‬

‫است و ريشه (‪ ، )Root‬دايرکتری والد آن است‪.‬‬

‫‪ 4‬ـ ‪ 2‬مجوزها‬ ‫هر فايلي يك سری مجوزهايي مربوط به خود دارد که تعیین مي‌کند چه کسي چه کاری با فايل انجام مي‌دهد ‪ .‬شايد شما تصمیم داريد‬

‫نامه‌های عاشقانه خود را در سیستمي نگه داريد و با سلسله مراتبي در دايرکتری مرتب کنید‪ .‬و نمي‌خواهید ديگران آن‌ها را بخوانند‪.‬‬

‫بنابراين شما مي‌توانید مجوزهای آن نامه‌ها را به طرح‌های نامفهومي تغییر دهید‪ .‬و يا مي‌توانید مجوزها را به دايرکتری‌هايي که شامل‬

‫نامه‌هاست تغییر دهید و بدين وسیله آن‌ها را از دسترس ديگران دور کنید‪.‬‬

‫اما در اينجا هشدار مي‌دهیم که يك کاربر ويژه بر روی سیستم يونیکس قرار دارد که ‪ super-user‬خوانده مي‌شود‪ .‬که مي‌تواند هر‬ ‫فايلي را بر روی سیستم بخواند يا شناسايي کند‪ Root .‬که نام ويژه وروديست مزيت‌های ‪ super-user‬را در بر دارد که با اداره کننده‬

‫سیستم در حین مراقبت از سیستم استفاده مي‌شود‪ .‬اگر شما نام رم ز ‪ Root‬را بدانید‪ .‬يك فرمان به نا م ‪ Su‬موقعیت ‪ shper-user‬را‬ ‫گزارش مي‌دهد‪ .‬هر کس رمز ‪ super-user‬را بداند مي‌تواند نامه‌های شما را بخواند‪ .‬بنابراين موارد حساس را در اين فايل قرار ندهید‪.‬‬

‫اگر شما قصد پنهان‌کاری و اختفا داريد مي‌توانید داده‌های داخل فايل را تغییر داده تا ‪ super-user‬قادر به خواندن آن نباشد ( و يا‬

‫حداقل درك نکنند)‪ .‬از فرمان ‪ crypt‬استفاده کنید‪ .‬البته ‪ crypt‬نیز نمي‌توند کامل امن و مطمئن باشد ‪ supper-hser‬مي‌تواند فرمان‬

‫‪ crypt‬را نیز تغییر دهد و يك عملیات رمزنگاری بر روی الگوريتم ‪ crypt‬انجام دهد‪ .‬روش اولي امکان خطا دارد بنابراين ‪ crypt‬در‬ ‫عمل نسبتا ايمن است‪.‬‬

‫در زندگي واقعي امنیت و اطمینان مستلزم رمزنگاری است تا لو داده نشود و به آساني نیز حدس زده نشود‪ .‬گاهي اوقات سیستم اجرايي‬

‫خطاها برای کاربرهای خطاکار اين امکان را به وجود مي‌آورد تا مجوز ‪ super-user‬را به دست آورد‪ .‬نتیجه و کارايي اين امنیت در‬

‫متن‌های ذکر شده در کتابشناسي انتهای اين فصل مورد بحث قرار مي‌گیرد‪.‬‬

‫وقتي که شما وارد سیستم عامل مي‌شويد اسمي را تايپ مي‌کنید و تأکید داريد که شما آن شخصي هستید اسم رمز را تايپ کرده‌ايد ‪.‬‬

‫اين اسم منطبق بر اسم ورودی شماست‪ .ligin-id .‬البته سیستم شما را توسط شماره‌ها تشخیص مي‌دهد که ‪ user-id‬و يا ‪ uid‬خوانده‬


‫محیط برنامه سازی لینوکس‬

‫‪50/322‬‬

‫مي‌شود‪.‬‬

‫در حقیقت ‪ login-id‬متفاوت ممکن است ‪ uid‬يکسان داشته باشد‪ ،‬که آن را برای سیستم غیر قابل تشخیص مي‌سازد‪ .‬البته اين عمل‬

‫نسبتا نادر‪ ،‬به دليل امنیتي نامطلوب است‪ .‬گذشته از ‪ ،uid‬شما يك هويت شناسي گروهي ‪ group-id‬ترتیب مي‌دهید که شما را در رده‬

‫کاربرها قرار مي‌دهد‪ .‬همه کاربرها بر روی بسیاری از سیستم‌ها (بر خلف ‪ loging-id‬مثل ‪ )roat‬در گروهي به نام ‪ other‬قرار دارند‪.‬‬

‫ولي سیستم شما ممکن است متفاوت باشد‪ .‬سیستم فايل و سیستم يونیکس به طور کلي تشخیص مي‌دهند که شما با مجوز داده شده با‬ ‫‪ uid‬و ‪ group-id‬چه مي‌توانید بکنید‪.‬‬

‫فايل ‪ etc/passwd/‬يك سیستم رمزنگار است‪ .‬و تمام ياطلعات ورودی را شامل مي‌شود‪ .‬شما مي‌تونید ‪ uid‬و ‪ group-id‬را توسط‬ ‫يافتن نامتان در ‪ etc/passwd/‬پیدا کرده همانگونه که سیستم عمل مي‌کند‪.‬‬

‫‪$ grep you / etc / passwd‬‬ ‫‪you : g k m b c T r j o A com : 604 .1 : y. O. A . people : / usr/ you‬‬ ‫‪$‬‬ ‫زمینه‌ها و فیلدها در فايل رمزنگار توسط علمت « ‪ » :‬مجزا مي‌شوند و به صورت زيرطرح‌ريزی مي‌شوند‪.‬‬

‫‪login-id : en crypted – passwd : uid : group – ld : miscell any‬‬ ‫‪: login – directery : shell‬‬ ‫فايل‌های يك متن معمولي هستند و تفکیك ها و تعريف‌های فیلد قراردادی‌اند که مطابقت مي‌کند با برنامه‌های که از اطلعات داخل‬ ‫فايل استفاده مي‌کنند‪.‬‬

‫فیلد شل‪ ،‬اغلب خالیست و مستلزم اينست که شما از شل پیش‌ فرض به اين صورت استفاده کنید‪.‬‬

‫‪ . bin / sh /‬فیلدهای متفرقه ممکن است هر چیزی را در بر داشته باشد و اغلب شامل اسم و آدرس و شماره تلفن شما مي‌باشد‪.‬‬

‫توجه داشته باشید اسم رمز شما بر روی فیلد دوم ظاهر مي‌شود‪ ،‬البته تنها به صورت يك فرم رمزسازی شده‪ .‬هر کسي مي‌تواند اسم‬ ‫رمز را بخواند‪ .‬بنابراين به کمك رمز هر کس مي‌تواند به جای شما از آن استفاده کند‪ .‬وقتي شما اسم رمز را به ‪ login‬مي‌دهید او آن را‬

‫رمزسازی کرده و نتیجه را مقايسه مي‌کند با اسم رمز‪ ،‬رمزسازی شده ‪ . etc/passwd/‬اگر آن‌ها مطابقت کردند شما مي‌توانید وارد‬

‫سیستم شويد‪ .‬اين مکانیسم مؤثر است زيرا الگوريتم رمزسازی دارای يك ويژگیست که آن ورود از يك فرم خالي به يك فرم رمزسازی‬

‫شده به آساني صورت مي‌گیرد ولي معکوس اين عمل به سختي صورت‌پذير است‪ .‬ممکن است به صورت ‪g k m b c t r y o 4‬‬ ‫رمزسازی شود‪ ،‬اما بعد از دريافت نامه‪ ،‬برگشتن به حالت اولیه آسان نیست‪.‬‬

‫هسته تشخیص مي‌دهد که به شما اجازه خواندن ‪ etc / passwd /‬داده شده البته توسط نگاه کردن به مجوزهای فايل‪ .‬در اينجا برای هر‬

‫فايل سه نوع مجوز وجود دارد‪ .‬بخوانید (متن را امتحان کنید) بنويسید (متن را تغییر دهید) و اجرا کنید (به عنوان يك بنا آن را اجرا‬ ‫کنید‪ ).‬به عله مجوزهای متفاوت توسط افراد متفاوت اجرا مي‌شود‪ .‬به عنوان ماسك فايل شما يك سری مجوز خواندن ‪ ،‬نوشتن و اجرا‬ ‫کردن داريد‪ .‬گروه (‪ )group‬شما يك دستگاه مجزا دارد‪ ،‬هر شخص ديگری سه دستگاه دارد‪.‬‬

‫گزينه ‪ IS-1‬اطلعات مجوز را در میان ديگر چیزها چاپ مي‌کند‪.‬‬

‫‪IS – 1 / etc / passwd‬‬ ‫‪30 10 :40‬‬

‫‪Aug‬‬

‫‪5115‬‬

‫‪1 root‬‬

‫‪- rw – r – r - -‬‬

‫‪IS – Ig / etc / passwd‬‬ ‫‪1 adm‬‬

‫‪$‬‬

‫‪- rw – r - - r - -‬‬

‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪51/322‬‬

‫اين دو خط ممکن است مجموع ًا اينگونه تفسیر شود ‪ login-id root :‬و ‪group adm‬‬

‫‪ etc / passwd /‬مي‌باشند که به طول ‪ 5115‬بايت است و در تاريخ ‪ 30‬آگوست و ساعت ‪ 10 : 45‬دقیقه صبح اصلح شده و دارای‬ ‫يك پیوند است‪ .‬اولین اسم در سیستم فايل ممکن است پیوند را در قسمت بعدی مورد بحث قرار دهد) بسیاری از طرح‌های ‪ IS‬در يك‬

‫سیستم‪ ،‬مالك و گروه را به دست مي دهد‪.‬‬

‫خط – ‪ - - rw – r - - r‬نشان مي‌دهد که چگونه ‪ IS‬مجوزها را بر روی فايل نمايش مي دهد‪ .‬ابتدا نشان مي‌دهد که اين يك فايل‬

‫معمولي است ‪ ،‬اگر يك دايرکتری وجود داشت ‪ ،‬علمت ‪ ok‬در آنجا وجود دارد‪ .‬همه کارکتر ديگر بعدی يعني خواندن‪ ،‬نوشتن و اجرا‬

‫کردن يك مجوز‪ ،‬صاحب فايل را رمزگذاری مي‌کند‪( .‬بر مبنای ‪ uid( . rw‬يعني (‪ )root‬مالك مي‌خواند و مي‌نويسد اما فايل را اجرا‬

‫نمي‌کدن يك فايل قابل اجرا به جای خط تیره ‪ x‬دارد‪.‬‬

‫سه کاراکتر بعدی (‪ ) - - r‬مجوزهای گروه را رمزگذاری مي‌کنند‪ ،‬در اين حالت هر شخص در گروه و هر سیستم اداره کننده‌ای‬ ‫مي‌تواند فايل را بخواند ولي نمي‌تواند بنويسد يا اجرا کند‪ .‬سه‌تای بعدی (‪ )- - also r‬مجوزها را برای بقیه کابرهای روی سیستم‬

‫تعريف مي‌کند‪ ،‬در اين ماشین‪ root ،‬اطلعات ورودی برای کاربر را تغییر مي‌دهد‪ .‬اما هر کسي مي‌تواند فايل را برای يافتن اطلعات‬

‫بخواند‪ .‬يك انتخاب به ظاهر درست برای گروه ‪ adm‬مي‌تواند نوشتن مجوزها روی‬ ‫‪ etc/passwd /‬باشد‪.‬‬

‫فايل ‪ etc / group /‬اسم‌های گروه و ‪ group – id‬را رمزگذاری مي‌کند‪ .‬و مشخص مي‌کند کدام کاربر در کدام گروه است ‪etc / / .‬‬

‫‪ passwd‬تنها گروه ورودی را شناسايي مي‌کند‪ .‬فرمان ‪ newgrp‬مجوزهای گروه را به گروه ديگری تغییر داده ‪:‬‬ ‫هر کسي مي‌تواند بیان کند ‪$ .‬‬ ‫بنويسد‪.‬‬

‫‪ ed / etc / passwd‬و فايل ‪ passwd‬را ويرايش کند‪ .‬اما تنها ‪ root‬مي‌تواند معکوس تغییرها را‬

‫ممکن است از خود بپرسید که چگونه اسم رمز را مي‌توانید تغییر دهید در حالیکه اسم رمز فايل در حال ويراستن است‪ .‬برنامه‌ای که‬

‫اسم رمز را تغییر مي‌دهد ‪ passwd‬خوانده مي‌شود‪ .‬که ممکن است شما آن را در ‪ /bin/‬پیدا کنید ‪:‬‬

‫‪$ IS – 1 / bin / passwd‬‬ ‫‪– rwsr–x r–x‬‬ ‫‪1 root‬‬ ‫‪8454 Jan 4 1983 / bin / passwd‬‬ ‫‪$‬‬ ‫توجه داشته باشید که ‪ etc / passwd /‬فايل متني است که شامل اطلعات وروديست‪ .‬در حالیکه ‪ bin / passwd /‬در دايرکتر متفاوتي‬

‫فايلي است که شامل برنامه‌های قابل اجراست که به شما اجازه مي‌دهد اسم رمز اطلعات خود را تغییر دهید‪ .‬مجوزها بیان مي‌کنند که‬

‫هر کسي مي‌تواند فرمان را اجرا کند اما تنها ‪ root‬مي‌تواند اسم رمز زمان را تغییر دهد‪ S .‬که به جای ‪ X‬در فیلد اجرا برای فیلد ماسك‬

‫قرار مي‌گیرد بیان مي‌کند که وقتي فرمان اجرا مي‌شود‪ .‬در حالت ‪ ، root‬مجوزهايي که با مالك فايل هم‌خواني داشته باشد به دست‬ ‫مي‌آيند ‪.‬‬

‫دستگاهـ ‪ uid-bit‬يك نظريه ساده اما ظريف است‪ .‬که شمارش مشکلت ايمني را حل مي‌کند‪ .‬برای مثال نويسنده برنامه‌های بازی‬

‫مي‌تواند برنامه ‪ set-uid‬را برای صاحبش بسازد‪ .‬بنابراين او مي‌تواند يك فايل خطي را که از دسترس ديگر کاربرها دور شده به روز‬

‫کند‪ .‬اما مفهوم ‪ set-uid‬خطرناك است‪ bin / passwd / .‬بايد درست و صحیح باشد‪ .‬اما اگر درست نبود مي‌تواند اطلعات سیستم را‬

‫که تحت نظر ‪ root‬است را از بین ببرد‪ .‬اگر او مجوز ‪ rw sr wx rwx‬را داشته به وسیله هر کاربری که مي‌تواند فايل را به هر برنامه‌ای‬

‫که هر کاری مي‌کند رونوشت شود‪ .‬اين موضوع برایـ ‪ set-uid‬بسیار ضروری است‪ .‬زيراـ ‪ root‬به مجوزهای هر سیستمي فايلي‬


‫محیط برنامه سازی لینوکس‬

‫‪52/322‬‬

‫دسترسي دارد‪ .‬وقتي که فايلي تغییر مي‌کند ‪ ،‬سیستم ‪ , set – unix bit‬يونیکس را قطع مي‌کند تا خطر حوزه ايمني را کاهش دهد‪.‬‬

‫دستگاه ‪ uid bit‬قدرتمند است‪ ،‬اما به طور ابتدائي برای تعداد معدودی سیستم برنامه‌هايي نظیر ‪ passwd‬به کار مي‌رود‪ .‬بیائید به تعدادی‬

‫فايل معمولي نگاهي بیندازيم‪.‬‬

‫‪IS – 1 / bin / who $‬‬ ‫‪6348 mar 29 1983 / bin / who -‬‬

‫‪1 root‬‬

‫‪rwxrwxv–w‬‬

‫‪ who‬چیزيست که توسط هر شخصي قابل اجراست و توسط ‪ root‬قابل نوشتن است مصاحب گروهي مي باشد‪ .‬منظور از قابل اجرا‬ ‫بودن چیست وقتي که شما برای ‪ shell‬تايپ مي‌کنید ‪:‬‬ ‫‪$‬‬

‫‪who‬‬

‫به نظرمي‌رسد برای فايل‌هايي‌که ‪ who‬نامیده مي‌شود‪ ،‬در يك سری دايرکتری‪ ،‬يکي ازآن‌ها ‪ bin /‬است‪ .‬اگر او شبیه به يك فايل بود و‬ ‫فايل نیز يك مجوز قابل اجرا داشت ‪ ،‬شل به هسته فرمان اجرا شدنش را مي‌دهد‪ .‬هسته مجوزها را کنترل مي‌کدن و اگر معتبر بودند‬

‫برنامه را اجرا مي‌کند ـ توجه داشته باشید که يك برنامه تنها يك فايل است با مجوز قابل اجرا‪ .‬در فصل بعدی ما به شما برنامه‌هايي‬

‫نشان خواهیم داد که تنها يك فايل متني باشند و مي‌توانند مانند فرمان اجرا شوند زيرا دارای دستگاه مجوز اجرا هستند‪.‬‬ ‫مجوز دايرکتری مقداری متفاوت عمل مي‌کند‪ ،‬اما مبنای نظريه يکي است‪.‬‬

‫‪$ IS - Id‬‬ ‫‪d r w x r w x r 3 y-u‬‬ ‫‪80 sep 27 06 : 11‬‬ ‫‪$‬‬ ‫گزينه ‪ IS-d‬بیشتر در مورد دايرکتری صحبت مي‌کنند تا در مورد اطلعاتش و منجر شدن ‪ d‬به يك علمت خروجي‪ .‬يك فیلد ‪ r‬يعني ‪،‬‬

‫شما مي‌توانید دايرکتری را بخوانید‪ .‬در نتیجه شما مي‌توانید بفهمید که چه فايلي در ‪( IS‬و يا ‪ )od‬وجود دارد‪ W .‬يعني شما مي‌توانید‬ ‫فايل‌ها را در اين دايرکتری حذف يا اضافه کنید‪ .‬زيرا او فايل دايرکتری را تغییر مي‌دهد و سپس مي‌نويسد‪ .‬در واقع شما نمي‌توانید به‬

‫راحتي روی يك دايرکتری بنويسد حتي اقدام ‪ root‬برای انجام اين کار ممنوع است‪.‬‬

‫‪$‬‬ ‫‪who‬‬ ‫’‪try to wer write ‘.‬‬ ‫‪. : cannot creat‬‬ ‫‪you can’t‬‬ ‫‪$‬‬ ‫در عوض سیستمي وجود دارد که مي‌تواند فايل‌ها را حذف و اضافه کند و تنها در حین آن ممکن است اطلعات دايرکتری را تغییر داد‪.‬‬

‫نظريه مجوزها اينگونه کاربرد دارد که فیلد ‪w‬‬

‫استفاده کند‪.‬‬

‫بیان مي‌کند که چه کسي مي‌تواند از روال سیستم برای تغییر و يا اصلح دايرکتری‬

‫اجازه حذف فايل به خود فايل بستگي ندارد‪ .‬اگر شما مجوز را بر روی دايرکتری نوشته‌ايد‪ ،‬مي‌توانید همانجا فايل را حذف کنید‪ ،‬حتي‬

‫اگر فايل در قبال نوشتن محافظت شده باشد‪ .‬فرمان ‪ rm‬قبل از حذف کردن يك فايل حفاظت شده‪ ،‬اجازه مي‌گیرد‪ .‬به هر حال به منظور‬

‫اطمینان يافتن از اينکه شما واقعا ً مي‌خواهید حذف کنید‪ ،‬در مواقع نادری برنامه يونیکس مقصود شما را دوباره کنترل مي‌کند‪( .‬علمت‬ ‫‪ F‬به روی ‪ rm‬باعث مي‌شود که حذف فايل بدون اجازه دوباره انجام پذيرد) فیلد ‪ X‬در مجوز برای يك دايرکتری به معني اجرا شدن‬ ‫نمي‌باشد‪ .‬بلکه معني آن جستجو کردن است مجوز اجرا‪ ،‬برای دايرکتری مشخص مي‌کند که آيا دايرکتری برای فايل جستجو شده‬

‫است‪ .‬بنابراين ايجاد يك دايرکتری با وضعیت ( ‪ )X - -‬برای بقیه کاربرها امکان دارد‪ .‬که اين مستلزم آن است که کاربرها به هر فايلي‬ ‫که ‌آن‌ها در مورد دايرکتری‌اش مي‌دانند دسترسي داشته باشند‪ .‬ولي ممکن است ‪ IS‬را اجرا نکند و حتي آن را نخواند و نمي‌داند که‬

‫فايل کجا قرار دارد‪ .‬مجوز دايرکتری (‪ )- - r‬نیز همینگونه است‪ .‬کاربر مي‌تواند ‪ IS‬را ببیند اما نمي‌تواند از محتوای دايرکتری استفاده‬


‫محیط برنامه سازی لینوکس‬

‫‪53/322‬‬

‫کند‪ .‬بسیاری از تأسیسات از اين وسیله برای قطع کردن ‪ usr games /‬در طول ساعات شلوغ استفاده مي‌کنند‪.‬‬

‫فرمان ‪( chmod‬وضعیت متغیر) مجوزهای روی فايل را تغییر مي‌دهد‪.‬‬

‫‪$ chomed permissions filemond‬‬ ‫نحو و دستور زبان مجوزها بد ترکیب و ناهنجار است‪ .‬آن‌ها مي‌توانند به دو روش مشخص شوند‪ .‬يکي به روش اعداد اکتال و يا با‬

‫توصیفات نمادی‪ .‬اعداد اکتال برای استفاده آسانتر هستند‪ .‬اما توصیفات نمادين بعضي وقت‌ها مناسب تر است‪ .‬زيرا آنها تغییرات مربوطه‬ ‫را در مجوزها مشخص مي‌کنتد بهتر است شما بگوئید ‪:‬‬

‫‪chomd rw – rw – rw – junk‬‬

‫تا اينکه بگوئید‬

‫‪$‬‬

‫‪$ chomd‬‬ ‫‪G G G junk‬‬ ‫مدهای اکتال توسط بهم بستن با يکديگر مشخص مي‌شوند‪ .‬عدد ‪ 4‬برای خواندن ‪ 2 ،‬برای نوشتن و ‪ 1‬برای اجرا کردن‪ .‬اين سه رقم‬

‫مشخص مي‌کنند که ‪ IS‬مجوزی برای مالك ‪ ،‬گروه و هر شخص ديگريست‪ .‬کدهای نمادی برای شرح و بسط دادن بسیار مشکل‬

‫هستند‪ .‬شما برای دستیابي به توصیفات کاملتر مي‌توانید به ‪ )chmod )1‬نگاه کنید‪ .‬برای اهداف‪ ،‬توجه داشته باشید که ‪ +‬يعني وصل‬ ‫کردن مجوز‬

‫ـ يعني قطع کردن مجوز برای مثال …‬

‫‪chmod + x commond‬‬

‫شخص را وارد کنید تا اين فرمان را اجرا کند‪.‬‬

‫‪chmod – w file‬‬

‫‪$‬‬

‫‪$‬‬

‫و سپس مجوز نوشتن را كه شامل مالك فايل است را قطع كنيد‪ .‬به جز موارد عدم تعهد‬ ‫در مورد ‪ super – user‬مالك فايل مجوز فايل را بدون توجه به مجوزها تغيير مي‌دهد‪ .‬حتي اگر‬ ‫شخص ديگري شما را وادار كند كه فايل را بنويسيد‪ ،‬سيستم به شما اجازه نمي‌دهد كه‬ ‫بيت‌هاي مجوزش را تغيير دهيد‪.‬‬ ‫‪704 sep 25‬‬

‫‪IS – Id / user / mary‬‬ ‫‪d r w x r w a r w x 5 mary‬‬ ‫‪chmod 444 / usr / mary‬‬ ‫‪chmod : can’t change / usr / mary‬‬

‫‪$‬‬ ‫‪$‬‬

‫‪$‬‬ ‫اگر دايرکتری قابل نوشتن باشد مي‌توانید فايل را بدون توجه به مجوز روی فايل‌ها حذف کنید‪ .‬اگر شما مي‌خواهید مطمئن شويد که‬

‫شما يا دوستتان فايل را هرگز از روی دايرکتری حذف نمي‌‌کنید‪ ،‬مجوز وشتن را از آن حذف کنید‪.‬‬

‫‪$‬‬ ‫‪$‬‬ ‫‪$‬‬ ‫‪$‬‬

‫‪cd‬‬ ‫‪date > temp‬‬ ‫‪chmod – w.‬‬ ‫‪Is – Id .‬‬ ‫‪dr – xr – xr – x‬‬ ‫‪3 you‬‬ ‫‪rm : temp‬‬ ‫‪not removed‬‬ ‫‪$ chmod‬‬ ‫‪77 5‬‬ ‫‪$ Is - Id‬‬ ‫‪d r w x r w x r -x‬‬ ‫‪3 you‬‬ ‫‪$ rm‬‬ ‫‪temp‬‬


‫محیط برنامه سازی لینوکس‬

‫‪54/322‬‬

‫‪$‬‬ ‫‪ temp‬در ايجا آمده شده است‪ .‬توجه داشته باشید که تغییر دادن مجوز روی دايرکتری بر روی ديت‌های متغیر تأثیری ندارد‪ .‬ديت‌های‬ ‫متغیر بر روی تغییرات محتوای فايل مؤثر است ‪ ،‬و نه بر وضعیتش‪ .‬مجوزها و ديت‌ها بر روی خود فايل ذخیره نمي‌شوند‪ ،‬بلکه روی‬

‫ساختار سیستم که ثرة شاخص (‪ )index nod‬نامیده مي‌شود ذخیره مي‌شود‪.‬‬ ‫‪ 5‬ت‪ :  inodes  2  ‬‬

‫هر فايلي دارای عناصر متعددی است‪ .‬نام ومحتوا‪ ،‬اطلعات اداره کننده مانند مجوزها و زمان‌های اصلح اطلعات ذخیره کننده که در‬

‫‪ inode‬ذخیره مي‌شود و با ضرورت داده‌های سیستم سروکار دارد مانند ‪ :‬کجای ديسك محتوای فايل ذخیره شده و چقدر طولني‬

‫مي‌باشد و غیره ……‬

‫سه زمان در ‪ inode‬وجود دارد‪ .‬طول مدتي که محتوای فايل اصلح يافت و نوشته شد‪ ،‬طول مدتي که فايل استفاده شد (خوانده شد يا‬ ‫اجرا شد) و مدتي که ‪ inode‬تغییر يافت‪ .‬که در اين مورد مي‌توان تشکیل مجوزها را مثال زد‪.‬‬

‫‪$‬‬

‫‪date.‬‬ ‫‪The sep 27 12 : 07 : 24‬‬ ‫‪EDT 1983‬‬ ‫‪$ date > junk‬‬ ‫‪- rw – rw – rw – 1 you‬‬ ‫‪$ Is – Iw junk‬‬ ‫‪- rw – rw – rw junk‬‬ ‫‪$ Is – Ic junk‬‬ ‫‪- rw – rw – rw - 7 you‬‬ ‫‪$‬‬ ‫تغییر محتوای فايل به زمان کاربرد آن تأثیری ندارد‪ .‬همانگونه که گفته شد توسط ‪ Is-Iu‬و تغییر مجوزها تنها بر روی زمان تغییر ‪inode‬‬ ‫مؤثر است طبق گفته‌های پیشین توسط ‪. Is-Ic‬‬

‫‪$ chmod 444 junk‬‬ ‫‪$ Is – Iu junk‬‬ ‫‪- r - - r - - r - - 1 you‬‬ ‫‪29 sep 27 06:11 junk‬‬ ‫‪$ Is – Ic junk‬‬ ‫‪- r - - r - - r - - 1 you‬‬ ‫‪29 sep 27 12 : 11 junk‬‬ ‫‪$ chmod 666 junk‬‬ ‫‪$‬‬ ‫گزينه ‪ ، Is-t‬که فايل‌ها را برطبق زمان ذخیره مي‌کند توسط پیش‌بیني مدت اصلح‪ ،‬مي‌تواند ترکیبي از – ‪ C‬يا – ‪ u‬باشد‪ .‬که بیان‬ ‫مي‌کند کدام ‪ inodes‬تغییر کرده و يا کدام فايل خوانده شده‪.‬‬

‫‪$‬‬

‫‪Is recipes‬‬ ‫‪cookie‬‬ ‫‪pie‬‬ ‫‪$ Is – Iwt‬‬ ‫‪total 2‬‬ ‫‪d r w x r w x r w x 4 you‬‬ ‫‪- rw – rw – rw – 1 you‬‬ ‫‪$‬‬ ‫‪ recipes‬اخیرا خیلي استفاده شده بود‪ .‬و ما نگاهي به محتوايش نیز انداختیم‪ .‬درك کردن ‪ inodes‬بسیار مهم است‪ ،‬نه تنها به خاطر‬


‫محیط برنامه سازی لینوکس‬

‫‪55/322‬‬

‫فهمیدن گزينه ‪ Is‬بلکه به خاطر اينکه در يك مفهوم قوی ‪ inoder‬يك فايل است‪ .‬سلسله مراتب دايرکتری ـ نام‌های مناسبي برای فايل‌ها‬

‫فراهم مي‌سازد‪ .‬نام داخلي هر سیستم برای هر فايل ‪ I-number‬است‪ .‬شماره‌های ‪ inode‬اطلعات فايل را در بر دارد‪ Is-1 .‬بیانگر ‪I-‬‬

‫‪ number‬در سیستم‌دهي (مبنا ده) است‪.‬‬

‫‪$ date > x‬‬ ‫‪$ Is – i‬‬ ‫‪1 5 7 6 8 junk‬‬ ‫‪1 5 2 7 4 recipes‬‬ ‫‪15852 x‬‬ ‫‪$‬‬ ‫دو بايت اول در ورودی دايرکتری تنها رابطه بین نام فايل و محتوايش مي‌باشد‪ .‬نام فايل‌ها در هر دايرکتری يك پیوند خوانده مي‌شود‬ ‫زيرا او يك نام از سلسله مراتب دايرکتری را به ‪ inode‬پیوند مي‌دهد‪ i-number .‬يکسان مي‌تواند در بیش از يك دايرکتری ظاهر شود‪.‬‬

‫فرمان ‪ inode , rm‬را حذف نمي‌کند‪ .‬او ورودی دايرکتری يا پیوندها را حذف مي‌کند‪ .‬تنها وقتي آخرين پیوند با فايل ناپديد شود ‪،‬‬

‫سیستم‪ inode ،‬را حذف مي‌کند‪ .‬اگر ‪ i-number‬در يك ورودی سیستم صفر باشد‪ ،‬به اين معني است که پیوند حذف شده است‪ .‬نه‬ ‫محتوای فايل‪ .‬ممکن است پیوندهای ديگری نیز وجود داشته باشد‪ .‬شما مي‌توانید اثبات کنید که ‪ i-number‬از طريق حذف کردن‪ ،‬به‬

‫طرف صفر مي‌رود‪.‬‬

‫فايل بعدی که در اين دايرکتری ساخته شده است‪ ،‬به سوی يك شکاف بل استفاده پیش خواهد رفت‪ .‬گرچه ممکن است ‪i-number‬‬

‫متفاوتي داشته باشد‪.‬‬

‫فرمان ‪ In‬يك پیوند با فايل کنوني مي‌سازد‪$ .‬‬

‫‪Inold – file new file‬‬

‫هدف از پیوند‪ ،‬دادن دو نام به يك فايل يکسان است‪ .‬زيرا اغلب مي‌تواند به صورت دوايرکتری متفاوتي ظاهر شود‪ .‬در بسیاری از‬

‫سیستم‌ها پیوند با ‪ bin / ed called / bine / e /‬وجود دارد‪ ،‬که مي‌تواند ويراستارها را ‪ e‬بخواند‪ .‬دو پیوند با فايل به ‪ inode‬مشابهي‬ ‫اشاره دارد‪.‬‬

‫‪$ In junk likt ojunk‬‬ ‫‪$ Is – Ii‬‬ ‫‪total 3‬‬ ‫‪1 5 7 6 8 - rw – rw – rw - 2 you‬‬ ‫‪1 5 7 6 8 - rw – rw – rw - 2 you‬‬ ‫‪1 5 2 7 4 d r w x r w x r w x 4 you‬‬ ‫‪$‬‬ ‫عدد صحیح چاپ شده بي نمجوزها و ماسك‌ها عدد پیوند با فايل است‪ .‬زيرا هر پیوندی به ‪ inode‬اشاره دارد‪ .‬همه پیوندها با طور‬ ‫يکساني اهمیت دارند‪ .‬هیچگونه تفاوتي میان اولین پیوند و پیوند بعدی وجود ندارد‪ .‬توجه داشته باشید که مجموع فضای ديسك که با‬

‫‪ Is‬محاسبه شده اشتباه است زيرا دوبار حساب شده است‪.‬‬

‫وقتي که فايلي را تغییر مي‌دهید‪ ،‬دستیابي به فايل‪ ،‬تغییرها را آشکار مي‌سازد‪ .‬البته تا زمانیکه پیوندها به فايل مشابهي اشاره داشته باشند‪.‬‬

‫‪$ echo x > junk‬‬ ‫‪$ Is – I‬‬ ‫‪total 3‬‬ ‫‪- rw – rw – rw – 2 you‬‬ ‫‪- rw – rw – rw – 2 you‬‬ ‫‪d rw x rw x rx x 4 you‬‬


‫محیط برنامه سازی لینوکس‬

‫‪56/322‬‬

‫‪$ rm link to junk‬‬ ‫‪total 2‬‬ ‫‪-rw – rw – rw – 1 you‬‬ ‫‪drw x rw x rw x 4 you‬‬ ‫‪$‬‬ ‫بعد از اينکه ‪ link to junk‬حذف شود‪ ،‬شمار پیوندها به يك باز مي‌گرد همانطور که قبل نیز گفتیم عملیات ‪ rm‬به روی فايل تنها‬ ‫پیوند را مي‌شکند‪ .‬فايل تا وقتي که آخرين پیوند وجود داشته باشد حفظ مي‌شود‪ .‬البته در عمل‪ ،‬بسیاری از فايل ها تنها يك پیوند دارند‪.‬‬

‫اما ما دوباره شاهد نظريه ساده‌‌ای هستیم که انعطاف پذيری بزرگي را فراهم مي‌کند‪.‬‬

‫پیوندی با فايل برقرار مي‌شود‪ ،‬داده‌ها غیر قابل برگشتند‪ .‬فايل حذف شده رو به نابودی و سوختن مي‌رود‪ .‬و هیچ راهي برای بازگرداندن‬

‫آن‌ها از خاکستر شدن نیست‪( .‬امید ضعیفي برای تجديد حیات وجود دارد‪ ،‬بسیاری از سیستم‌های يونیکس بزرگ دارای فرايند پشتیباني‬ ‫هستند که از تغییرات فايل‌ها مانند نوار مغناطیسي کپي مي‌گیرند‪ .‬از اين به بعد آن‌ها مي‌توانند قابل برگشت باشند‪ .‬برای اطمینان خاطر‬

‫شما بايد بدانید که پشتیبان تا چه حد از سیستم شما حفاظت مي‌کند‪ .‬اگر پشتیباني وجود نداشته باشد مشاهده مي‌کنیم که ديسك دچار‬ ‫خرابي بدی مي‌شود‪.‬‬

‫پیوند با فايل قابل دسترسي است‪ ،‬وقتي دو نفر مي‌خواهند در يك فايل با هم سهیم باشند‪ .‬اگر گاهي شما مي‌خواهید فايل ها را تفکیك‬ ‫کنید (يك فايل متفاوت با اطلعات يکسان) شما مي‌توانید از مدارك کپي بگیريد قبل از آنکه تغییرات زيادی در آن ايجاد شود‪ .‬برای‬

‫مثال شما مي‌توانید اطلعات اصلي را بدون هیچ تغییری دوباره ذخیره کنید‪ .‬ساختن پیوند کمکي نمي‌کند‪ ،‬زيرا وقتي د اده‌ها تغییر کند‬ ‫پیوندها نیز تغییر مي‌کنند‪ CP .‬کپي‌های فايل را تشکیل مي‌دهند‪.‬‬

‫‪$ cp junk copy of junk‬‬ ‫‪$ Is – Ii‬‬ ‫‪total 3‬‬ ‫‪1 5 8 5 0 - rw – rw – rw- 1 you‬‬ ‫‪15768‬‬ ‫‪- rw – rw – rw – 1 you‬‬ ‫‪15274‬‬ ‫‪drw x rw x rw x 4 you‬‬ ‫‪$‬‬ ‫‪ i-number‬برای ‪ junk‬و ‪ copy of junk‬متفاوت است‪ .‬زيرا فايل‌های متفاوتي هستند‪ .‬حتي اگر دارای محتوای يکساني باشند‪ .‬اغلب‬ ‫يك نظريه خوب به يك مجوز بر روی کپي پشتیبان تغییر مي‌يابد‪ ،‬بنابراين حذف کردن آن به طور تصادفي بسیار سخت است‪.‬‬

‫‪chmoe – w copy of junk‬‬

‫‪$‬‬ ‫⋮‬ ‫⋮‬

‫تغییر دادن کپي‌های فايل و حذف آن‌ها تغییری در اصل و مبدأ ايجاد نمي‌کند‪ .‬توجه داشته باشید که چون ‪ copy of junk‬نوشته است‬ ‫که مجوزها قطع شده‌اند‪ rm ،‬برای حذف فايل نیاز به تائید دارد‪.‬‬

‫برای اجرای عملیات فايل‌ها‪ ،‬بیش از يك فرمان وجود دارد‪،‬ـ ‪ mv‬فايل‌ها را با مرتب کردن پیوندها دوباره نامگذاری مي‌کند‪.‬‬

‫دستورالعمل آن به صورت ‪ cp‬و ‪ In‬است‪.‬‬

‫‪$ mv junk sam old junk‬‬ ‫‪$ Is – Ii‬‬ ‫‪total 2‬‬ ‫‪1 5 2 7 4 drw x rw x rw x 4 you‬‬ ‫‪1 5 7 6 8 - rw – rw – rw - 1 you‬‬


‫محیط برنامه سازی لینوکس‬

‫‪57/322‬‬

‫‪$‬‬

‫‪ some old junk‬شبیه همان فايل ‪ junk‬قبلي است‪ .‬به ‪ i-number‬نگاه کنید تنها نامش تغییر يافته (ورودی دايرکتری با ‪8 7 5 1‬‬ ‫‪ inode‬مرتبط است)‬

‫ما تمامي اين فايل‌ها را که در يك دايرکتری به صورت به هم ريخته بود‪ ،‬اجرا کرديم‪ .‬اما آن تنها در راستای دايرکتری عمل مي‌‌کند‪In .‬‬

‫برای برقراری ارتباط با نام‌های يکسان در دايرکتری‌های متعددی استفاده مي‌شود‪ .‬مانند وقتي که افراد زيادی در يك برنامه شرکت‬

‫دارند‪ mv .‬مي‌تاند فايل دايرکتری را به دايرکتي ديگری انتقال دهد‪ .‬در حقیقت آن‌ها اطلعات رايجي هستند که ‪ mv‬و ‪ cp‬دستور نحو‬ ‫خاصي برای آن‌ها دارند‪.‬‬

‫‪mv )or cp( file 1 file 2 … directory‬‬ ‫فرمان بال يك يا دو فايل را به دايرکتری که در آخرين مرحله است حرکت مي‌دهد ‪ .‬کپي‌ها و پیوندها با نام فايل‌های مشابهي ساخته‬

‫مي‌شوند‪ .‬برای مثال‪ ،‬اگر مي‌خواهید‪ ،‬مهارت خود را در ويراستاری امتحان کنید بايد با بیان اين فرمان آغاز کنید‪:‬‬ ‫اگر شما قصد داريد در يك شل کار کنید شماره فايل‌های منابع متفاوت را اينگونه بیان کنید‪.‬‬

‫‪cp / usr / src / cmd / ed‬‬

‫‪$‬‬

‫‪$‬‬ ‫‪$‬‬

‫‪mk dir sh‬‬ ‫‪cp / usr / src / end / sh * sh‬‬ ‫‪ cp‬از تمامي شل فايل‌های منبع از دايرکتری فرعي ‪ sh‬کپي برداری مي‌کند‪( .‬فرض مي‌کنیم ساختار دايرکتری فرعي به صورت ‪usr /‬‬ ‫‪ src / cnd / sh‬نمي‌باشد و ‪ cp‬نیز خیلي کارآمد نیست)‪.‬‬

‫در بسیاری از سیستم‌ها‪ In ،‬بحث‌‌های فايل چندگانه را مي‌پذيرد‪ .‬همچنین در مورد دايرکتری‌ها نیز همین گونه عمل مي‌کند‪ .‬و در‬

‫بسیاری از سیستم‌ها ‪ mv‬و ‪ cp‬و ‪ In‬تنها به يك فايل مرتبط است که نام خود را برای اجرای عملیات امتحان مي‌کند‪.‬‬

‫‪ 6‬ـ ‪ 2‬ـ سلسله مراتب دايركتري‬ ‫‪bin‬‬ ‫در فصل اول نگاهي بر روی سلسله مراتب سیستم فايل انداختیم که از ‪ usr / you /‬شروع مي‌شود‪ .‬اين بار قصد داريم در مورد آن با‬

‫يك روش برنامه‌ريزی شده تحقیق و بررسي کنیم‪ .‬که با بیش از سه ريشه (‪ )root‬آغاز مي‌شود‪.‬‬

‫‪Is / boot‬‬ ‫‪dev‬‬ ‫‪etc‬‬ ‫‪lib‬‬ ‫‪tmp‬‬ ‫‪unix‬‬ ‫‪usr‬‬

‫‪$‬‬

‫‪$‬‬ ‫‪ /‬يونیکس برای خود هسته يونیکس يك برنامه است‪ .‬وقتي سیستم شروع به کار مي‌کند ‪ unix /‬را از روی ديسك خوانده مي‌شود‪ .‬اين‬ ‫فرايند در دو مرحله رخ مي‌دهد‪ .‬ابتدا فايل ‪ boot /‬خوانده مي‌شود‪ ،‬سپس از روی ‪ unix/‬مي‌خواند‪ .‬اطلعات زيادی در مورد اين فرايند‬

‫سیستم خود راه‌انداز ممکن است در ‪ )boot )8‬يافت شود‪ .‬بقیه فايل در اسلش دايرکتری است که هر کدام قسمت‌های کاملي هستند که‬


‫محیط برنامه سازی لینوکس‬

‫‪58/322‬‬

‫مجموع سیستم فايل را به وجود مي‌آورند‪.‬‬

‫بیت‌ها را در دايرکتری مذکور پیدا کنید‪ .‬شما با طرح کلي سیستم فايل آشنايي زيادی داريد و مي‌توانید از آن استفاده کنید‪ .‬جدول ‪ 1‬ـ ‪2‬‬

‫فضاهای مناسبي را برای تماشا پیشنهاد کرده گرچه بسیاری از اسم‌ها به سیستم وابسته است‪.‬‬

‫‪ bin /‬را که قبل ديده‌ايم ‪ .‬آن يك دايرکتريست و جايي قرار مي‌گیرد که برنامه‌های اصلي نظیر ‪ who‬و ‪ ed‬قرار مي‌گیرند‪.‬‬ ‫‪ )dev )devies /‬که در بخش بعدی در موردش بحث خواهیم کرد‪.‬‬

‫‪ )etc )et ceterw /‬که آن را قبل ديده‌ايم که شامل فايل‌های اداره کننده متعددی نظیر ‪ passwd‬و بسیاری از برنامه‌های سیستمي نظیر ‪/‬‬

‫‪ etc / getty‬که همانند ابتدای کار ارزش دارد و با‬ ‫‪ bin/login /‬مرتبط است‪.‬‬

‫‪ etc / rc /‬فايل فرمان‌های شل است که بعد از سیستم خود راه‌انداز‪ ،‬اجرا مي‌شود‪.‬‬ ‫‪ etc / group /‬تعدادی از اين گروه را فهرست‌بندی کرده است‪.‬‬

‫‪ libclibrar /‬شامل قسمت‌هايي از کامپايلر است‪ .‬مانند ‪lib / cpp /‬‬

‫‪ tmp )temporaries0 /‬که مخزني برای فايل‌های کوتاه مدت که در طول اجرای برنامه ساخته شده‪ ،‬مي‌باشد‪ .‬وقتي که شما ويراستار‬ ‫‪ ed‬را راه‌اندازی مي‌کنید‪ ،‬برای مثال‪ ،‬او فايلي با نام ‪ tmp/e00512/‬مي‌سازد که تمامي کپي‌های فايل را در بر دارد‪ .‬در اين صورت شما‬

‫به جای اينکه با اصل فايل سروکار داشته باشید ‪ ،‬فايل را ويرايش کرده‌ايد‪ .‬البته اين فايل مي‌توانست در دايرکتری جاری شما ساخته‬

‫شود ولي بهتر است که در ‪ tmp /‬قرار گیرد‪ .‬گرچه ناخوشايند به نظر مي‌رسد‪ .‬شما ممکن است فايلي به نام ‪ e 00512‬در دايرکتری‬

‫خود داشته باشید‪ .‬وقتي سیستم شروع به کار مي‌کند‪ tmp / ،‬به طور خودکار پاك مي‌شود‪ .‬بنابراين اگر سیستم خراب شود‪،‬دايرکتری‬

‫شما يك فايل ناخواسته به دست نمي‌آورد‪ .‬اغلب ‪ tmp /‬بر روی ديسك مرتب مي‌شود تا سهل الوصول باشد‪.‬‬

‫در اين جا مشکلي وجود دارد که وقتي در ‪ tmp/‬برنامه‌های متعددی ساخته مي‌شود ممکن است آن‌ها به فايل‌های يکديگر رجوع کند‪.‬‬

‫به همین دلیل فايل موقت ‪ ed‬نام ويژه ‌ای دارد و تضمي مي‌شود که برنامه ديگری برای فايل موقت خود نام مشابه آن را انتخاب نکند‪.‬‬ ‫در فصل ‪ 5‬و ‪ 6‬چگونگي اين عمل را خواهیم ديد‪.‬‬

‫‪ usr /‬سیستم فايل کاربر خوانده مي‌شود‪ ،‬گرچه با کاربرهای اين سیستم کار زيادی نمي‌توان انجام داد ‪ .‬در ماشین‌های ما‪ ،‬دايرکتری‬ ‫ورودی‪ usr / buk , / usr / rob / ،‬مي‌باشند‪ .‬وقتي فايل شخصي شما در دايرکتری فرعي ‪ usr /‬قرار بگیرد‪ ،‬چیزهای زيادی در آنجا‬

‫وجود دارد که شما دوست داريد آنها را پیدا کنید‪ .‬در ‪ , /‬دايرکترهايي به نام‌های ‪ usr / bin /‬و ‪ usr / lib /‬و ‪ usr / tmp /‬قرار دارد‬

‫که عملیاتي شبیه به نام‌های خود را اجرا مي‌کنند و شامل برنامه‌هايي هستند که کمتر برای سیستم بحران ايجاد مي‌کند ‪ .‬برای مثال ‪nroff‬‬

‫در ‪ usr / bin /‬يافت مي‌شود و نه در ‪ bin /‬؛ مجموعه روال ‪ fortRan‬نیز در ‪ usr / lib /‬قرار دارد‪ .‬چیزی که بايد دانست اين است که‬

‫بحران‌ها در سیستم‌های مختلف‪ ،‬متفاوتند‪ .‬بعضي سیستم‌ها مانند ‪ th Edition 7‬که گسترش يافته نیز هست‪ ،‬تمامي برنامه‌های ‪ bin /‬را‬ ‫داراست و تمامي ‪ usr / bin/‬را لغو مي‌کند و از بین مي‌برد‪ .‬بقیه نیز به خاطر استفاده مکرر ‪ usr / bin /‬را به دو دايرکتری تقسیم‬

‫مي‌کند‪.‬‬

‫دايرکترهای ديگر در ‪ usr ، / usr / adm /‬مي‌باشند که شمارش اطلعات را شامل مي‌شوند‪.‬‬

‫‪ usr / dic /‬که يك فرهنگ لغت معمولي را در بر دارد‪ .‬راهنمای خط ـ وصل‪ ،‬در ‪ usr / man‬نگهداری مي‌شود‪ .‬برای مثال نگاهي‬

‫بیندازيد به‬

‫‪/ usr / man / man 1 / spen 1.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪59/322‬‬

‫اگر سیستم شما‪ ،‬خط ـ وصل منع کدرا داراست‪ ،‬شما مي‌توانید آن را در ‪ usr/src/‬پیدا کنید‪ .‬صر وقت برای يافتن فايل جديد ارزش‬ ‫زيادی دارد به خصوص در مورد ‪ usr /‬که چگونگي سازمان يافتن يك فايل و در کجا قرار داشتن آن را نشان مي‌دهد‪.‬‬

‫‪ 7‬ـ ‪ 2‬ـ دستگاه‌ها ‪ :‬‬ ‫ما قبلً گذری بر ‪ dev /‬داشته‌ايم‪ .‬همان طور که مي‌شود حدس زد ‪ dev /‬شامل فايل دستگاه است يکي از ظريف‌ترين نظريات در مورد‬ ‫سیستم يونیکس اين است که با دستگاه جانبي سروکار دارد‪ .‬مانند ديسك‪ ،‬دستگاه‌های نوار مغناطیسي ‪ ،‬چاپگر خطي‪ ،‬پايانه و …‬

‫فايلي به نام ‪ dev / mto /‬وجود دارد که در داخل هسته‪ ،‬چیزهايي که به اين فايل ارجاع داده مي‌شود به يك فرمان سخت افزاری‬

‫تبديل مي‌شود تا دستیابي به نوار مغناطیسي را ممکن سازد‪.‬‬

‫اگر برنامه بخواند ‪ dev / mto /‬اطلعات نوار مغناطیسي که به يك نوار ران نصب شده باز مي‌گردد‪.‬‬

‫‪$ cp / dev / mto junk‬‬ ‫فرمان بال اطلعات نوار مغناطیسي را بر روی فايلي به نام ‪ junk‬کپي مي‌کند‪ .‬در اينجا در مورد ‪ cp‬صحبتي نمي‌کنیم‪ .‬روی صحبتمان‬

‫تنها ‪ dev / mto /‬است‪ .‬اين فايلي‌ست که دارای بايت‌های هم‌تراز است‪.‬‬

‫اولین چیزی که بايد بدان توجه داشت اينست که به جای شمارش بايت‌ها يك جفت عدد صحیح وجود دارد و اينکه اولین کاراکترهای‬

‫مد همیشه ‪ b‬و يا ‪ c‬بوده‪ .‬به اين صورت ‪ IS‬اطلعات را از يك ‪ inode‬تايپ مي‌کند و دستگاه را از يك فايل عادی تغییر مي‌دهد‪.‬‬

‫‪Inode‬های يك فايل عادی شامل لیستي از بلوك‌های ديسك است‪ .‬که اطلعات فايل را ذخیره مي‌کند‪ .‬برای دستگاه فايل‪ inode ،‬به‬

‫جای اينکه شامل اسم‌های داخلي برای دستگاه باشد و به جای يك جفت شماره‪ ،‬به صورت مینو ر (‪ )minor‬و يا میژو ر (‪)major‬‬

‫خوانده مي‌شود‪ .‬ديسك و نوار مغناطیسي ‪ ،‬دستگاه‌های بلوك هستند و هر چیز ديگری مثل پايانه و يا چاپگر و خط تلفن‪ ،‬دستگاه‬

‫کارکتری هستند‪.‬‬

‫شماره میژور نوع دستگاه را کدگذاری مي‌کند‪ ،‬در حالیکه شماره مینور‪ /‬فواصل متفات دستگاه را تعیین مي‌کند‪ .‬برای مثال ‪dev / ttyo /‬‬ ‫و ‪ dev / tty 1 /‬دارای دو دهانه در کنترل‌کننده پايانه است‪ .‬بنابراين آن‌ها دارای شماره میژور مساوی اما شماره مینور متفاوتي هستند‪.‬‬

‫نام فايل‌های ديسك از دگرگوني سخت‌افزاری گرفته شده است‪ dev / rpo 0/ .‬و ‪ dev / rpo 1 /‬نام خود را از ديسك‌گردان ‪D E C‬‬ ‫‪ RP06‬که وارد سیستم شده است‪ ،‬گرفته‌اند‪.‬‬

‫تنها يك نوار دگرگون وجود دارد که به طور منطقي به دو سیستم فايل تقسیم شده است‪ .‬اگر نوار گردان دومي وجود داشت‪ ،‬فايل‌های‬ ‫مرتبط خود را اينگونه نام‌گذاری مي‌کردند‪.‬‬

‫اولین رقم‪ ،‬فعالیت نوار گردان مشخص مي‌کند و دومین رقم بخش‌های آن را‪.‬‬

‫‪/ dev / rp 10 / dev / rp 11‬‬

‫ممکن است از خود بپرسید چرا به جای يك فايل دستگاه ديسك‪ ،‬انواع متنعي از فايل‌های دستگاه ديسك وجود دارد‪ .‬به دليل تاريخي‬

‫و نگهداری آسان آن‪ ،‬سیستم فايل به دو سیستم فرعي کوچك تبديل مي‌شود‪ .‬فايل‌های داخل سیستم‌های فرعي به دايرکتری داخل‬

‫سیستم اصلي دسترسي دارد‪ .‬برنامه ‪ etc / mount /‬بیان مي‌کند که فايل دستگاه و دايرکتری با هم‪ ،‬هم‌خواني دارند ‪.‬‬

‫‪$ /etc/mount‬‬ ‫‪rp 01 on /usr‬‬ ‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪60/322‬‬

‫در اين حالت سیستم ‪ root ، / dev / rp 00‬را اشغال مي‌کند (که اين توسط دايرکتری‌های فرعي‌يش ـ بر روی ‪ ، dev / rp 01‬قرار‬

‫مي‌گیرد‪.‬‬

‫سیستم فايل ‪ root‬بايد به سیستم نشان داده شود‪ ،‬تا اجرا شود‪ dev / bin / .‬و ‪ etc /‬در سیستم ‪ root‬ادامه پیدا مي‌کند‪ .‬و بسیاری از‬

‫سیستم‌های ‪ bin / sh /‬بايد اجرا شود‪ .‬در حین اين عملیات خود راه‌انداز‪ ،‬همه سیستم‌های فايلي چك مي‌شوند و به سیستم فايل‬ ‫مي‌پیوندند اين عملیات پیوند ‪( mounting‬نصب کردن) نام دارد‪ .‬يك نرم افزار با نصب يك بسته ديسك جديد بر ديسك ران برابری‬

‫مي‌کند که توسط ‪ super – user‬انجام مي‌گیرد بعد از اينکه ‪ dev / rp 01 /‬به عنوان ‪ usr /‬نصب شد‪ ،‬فايل در سیستم فايل کاربر قابل‬ ‫دسترسي است گويي که آن‌ها جزئي از سیستم ‪ root‬هستند‪.‬‬

‫يك مشکلي که وجود دارد اينست که شماره‌های ‪ inode‬در سیستم‌های فايلي متفاوت‪ ،‬منحصربه‌فرد نیستند‪ .‬هر سیستم فرعي دارای‬

‫سايزها و ‪inode‬های مشخص و معیني است‪( .‬شماره بلوك قابل دسترسي در هر فايل)‪ .‬اگر سیستم فرعي پر شود بزرگ کردن فايل در‬

‫سیستم فرعي غیرممکن است تا زمانیکه مکان جديدی احیا شود‪ .‬فرمان ‪( df‬مکان باز ديسك) فضای مناسبي را روی سیستم فايل نصب‬ ‫شده درخواست مي‌کند‪.‬‬

‫‪$‬‬

‫‪df‬‬ ‫‪/ dev / rp 0 0‬‬ ‫‪1989‬‬ ‫‪/ dev / rp 01‬‬ ‫‪21257‬‬ ‫‪ usr ، 21257 /‬بلوك آزاد دارد‪ .‬اينکه آيا اين يك فضای وسیع است يا نه به چگونگي استفاده از سیستم بستگي دارد‪ .‬بعضي از اين‬

‫تأسیسات به فضای بیشتي در فايل نیاز دارند‪ .‬فرمانـ ‪ df‬تنوع وسیعي در فرمت خروجي دارد‪ .‬خروجيـ ‪ df‬شما ممکن است کمي‬

‫متفاوت به نظر برسد‪ .‬وقتي که شما وارد سیستم عامل مي‌شويد يك خط پايانه و يك فايلـ ‪ dev /‬به دست مي‌آوريد که تمامي‬

‫کارکترهايي را که تايپ کرده و به دست آورده‌ايد را ارسال مي‌کند ‪ .‬فرمان ‪ tty‬بیان مي‌کند که شما از کدام پايانه استفاده کرده‌ايد ‪.‬‬

‫‪$‬‬

‫‪who am 1‬‬ ‫‪you‬‬ ‫‪tty 0‬‬ ‫‪sep 28 01 : 02‬‬ ‫‪$ tty‬‬ ‫‪/ dev / ttyo‬‬ ‫‪$ Is – 1 / dev / ttyo‬‬ ‫‪crw - - w - - w – 1 you‬‬ ‫‪1 , 12 sep‬‬ ‫‪28‬‬ ‫‪02 : 04 / deve / ttyo‬‬ ‫‪$ date‬‬ ‫‪> / dev / ttyo‬‬ ‫‪wed‬‬ ‫‪sep‬‬ ‫‪28 02 : 40 : 51 Edt‬‬ ‫‪1983‬‬ ‫‪$‬‬ ‫توجه داشته باشید که شما مالك دستگاه هستید و تنها شما اجازه خواندن آن را داريد به عبارت ديگر هیچ کس ديگری نمي‌تواند به طور‬ ‫مستقیم کارکترهايي را که تايپ کرده‌ايد بخواند ولي ممکن است بتواند بر روی پايانه چیزی بنويسد ‪ .‬برای جلوگیری از اين عمل شما‬ ‫مي‌توانید از ‪ chmod‬و يا ‪ mesg‬استفاده کنید‪.‬‬

‫‪$ mesg N‬‬ ‫‪$ Is – 1‬‬ ‫‪/ dev / ttyo‬‬ ‫ ‪crw - - - - - -‬‬‫‪1 you‬‬ ‫‪$ mesg y‬‬ ‫‪$‬‬ ‫مي‌توان توسط نام به پايانه‌ای که از آن استفاده مي‌کنیم رجوع کرد ‪ .‬دستگاه ‪ dev / tty /‬مفهومي برای پايانه ورودی شما محسوب‬

‫مي‌شود و مي توان فهمید که از کدام پايانه استفاده مي‌کنیم ‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪61/322‬‬

‫‪date > / dev / tty‬‬ ‫‪wed sep 28 02 : 42 : 23‬‬

‫‪$‬‬

‫‪EDT 1983‬‬ ‫‪$‬‬ ‫وقتي که برنامه‌ای به واکنش در مقابل کاربر نیاز دارد مي‌توان از ‪ dev / tty /‬استفاده کرد حتي اگر ورودی و خروجي استاندارد آن با‬

‫فايل‌ها در ارتباط باشد‪ Crypt .‬اولین برنامه‌ای است که از ‪ dev / tty/‬استفاده مي‌کند‪ .‬يك متن واضح « ‪ » clear teat‬که از ورودی‬

‫استاندارد وارد مي‌شود و داده‌های رمزگذاری شده به خروجي استاندارد مي‌روند بنابراين ‪ crypt‬کلید رمز را از ‪ dev / tty /‬مي‌خواند‪.‬‬

‫‪$ crypt < c 1 ear text > crypted text‬‬ ‫‪Enter key :‬‬ ‫‪$‬‬ ‫استفاده از ‪ dev / tty /‬در اين مثال صريح نیست ولي در آن وجود دارد‪ .‬اگر ‪ crypt‬کلید را از ورودی استاندارد بخواند‪ ،‬پس اولین خط‬ ‫متن پاك « ‪ »‌cleartext‬را مي‌تواند بخواند‪ .‬بنابراين به جای اينکه ‪ crypt‬رمز ‪ dev / tty /‬را باز کند‪ ،‬کارکترهای خودکار را قطع مي‌کند‬ ‫و کلید رمز شما روی صفحه پديدار نمي‌شود‪ .‬در فصل ‪ 5‬و ‪ 6‬به اين مطلب بیشتر اشاره خاهیم کرد‪.‬‬

‫گاهي شما مي‌خواهید برنامه‌ای را اجرا کنید‪ ،‬اما اهمیتي نمي‌دهید که از کدام ورودی استفاده مي‌کنید ‪ .‬برای مثال شما به اخبار امروز‬

‫نگاهي انداخته‌ايد و ديگر نمي‌خواهید آن را بخوانید‪ .‬اگر فرمان ‪ news‬را به فايل ‪ dev / nu 11 /‬بدهید باعث مي‌شود خروجي آن‬ ‫حذف شود‪.‬‬

‫‪$‬‬ ‫‪news > / dev / nu 11‬‬ ‫‪$‬‬ ‫داده‌های نوشته شده در ‪ dev / nu 11 /‬بدون هیچ دستوری وقتي حذف مي‌شوند که برنامه‌های خوانده شده از ‪ dev / nu 11 /‬تمام‬

‫شود‪ ،‬زيرا خواندن ‪ ، dev / nu 11 /‬بايت‌ها را صفر مي‌کند‪.‬‬

‫استفاده رايج از ‪ dev / nu 11 /‬حذف کردن يك خروجي عاديست‪ .‬بنابراين پس از آن پیغام خطاشناسي پديدار مي‌شود‪ .‬برای مثال‬ ‫فرمان ‪ time‬کاربرد ‪ cpu‬را برای يك برنامه بیان مي‌کند‪ .‬اطلعات بر روی خطای استاندارد تايپ مي‌شود‪.‬‬

‫‪$‬‬

‫‪Is – 1 / usr / dict / words‬‬ ‫‪-r--r --r--1‬‬ ‫‪bin‬‬ ‫‪$ time grep e / usr / dict / words > / dev / nu 11‬‬ ‫‪real‬‬ ‫‪8.0‬‬ ‫‪user‬‬ ‫‪3.9‬‬ ‫‪sys‬‬ ‫‪2.8‬‬ ‫‪$‬‬

‫اعداد در خروجي زمان‪ ،‬سپری شدن زمان را نشان مي‌دهند و زمان ‪ cpu‬در برنامه سپری مي‌شود و هنگامي که برنامه در جريان است‬

‫زمان ‪ cpu‬در هسته سپری مي‌شود‪.‬‬

‫‪ Egrep‬گونه قدرتمندی از ‪ grep‬مي‌باشد که در بخش ‪ 4‬در موردش بحث خواهیم کرد و هنگام جستجوی يك فايل بزرگ سرعتش دو‬

‫برابر ‪ grep‬مي‌شود‪ .‬اگر فرم خروجي ‪ grep‬و ‪ egrep‬به‬

‫‪ dev / nu 11 /‬فرستاده نشد ما مي‌توانیم منتظر صدها هزار کارکتری باشیم که ظاهر مي‌شوند روی پايانه قبل از يافتن اطلعات زمان‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪62/322‬‬

‫فصل ‪ :۳‬استفاده از شل‬ ‫شل ـ برنامه‌ای که درخواستهای شما را برای اجرای برنامه‌ها تفسیر مي‌کند ـ مهمترين برنامه برای اکثر استفاده‌کنندگان از يونیکس‬

‫مي‌باشند؛ با استثنای ممکن از ويراستار متن مورد علقه خود‪ ،‬شما زمان بیشتری را درخصوص کار با شل نسبت به هر برنامه ديگری‬

‫سپری مي‌کنید‪ .‬در اين فصل و در فصل ‪ ،۵‬ما زمان قابل توجهي را به توانايي‌های شل اختصاص مي‌دهیم‪ .‬نکته مهمي که ما مي‌خواهیم‬ ‫نشان دهیم اين است که شما مي‌توانید عملکردهای زيادی را بدون کار خیلي سخت و مطمئناًـ بدون ذخیره کردن مجدد برای‬ ‫برنامه‌نويسي در يك زبان قراردادی مانند ‪ C‬انجام دهید‪ ،‬اگر شما بدانید که چگونه از شل استفاده کنید‪.‬‬

‫ما شمول خود درخصوص شل را به دو فصل تقسیم کرده‌ايم‪ .‬اين فصل يك مرحله را فراتر از ضرورتهای ارائه شده در فصل ‪ ۱‬برای‬ ‫برخي از ويژگیهای تصوری شل اما عموما ً استفاده شده‪ ،‬بیان مي‌کند‪ .‬مانند فراکاراکترها‪ ،‬نقل قول کردن‪ ،‬ايجاد فرمانهای جديد‪ ،‬عبور‬

‫آ‌رگومان‌ها درون آنها‪ ،‬استفاده از متغیرهای شل و برخي از روند کنترل اولیه‪ .‬موضوعاتي وجود دارند که شما بايد برای استفاده خود از‬

‫شل بدانید‪ .‬اطلعات موجود در فصل ‪ ،۵‬عمیق‌تر بیان مي‌شوند ـ اين فصل برای نوشتن برنامه‌های مهم شل اختصاص دارد‪ ،‬برنامه‌هايي‬ ‫که برای استفاده توسط ديگران ضد گلوله مي‌باشند‪ .‬تقسیم بین دو فصل تا اندازه‌ای اختیاری مي‌باشد‪ ،‬البته هر دو فصل نهايتاً بايد مطالعه‬

‫شوند‪.‬‬

‫‪ ۳.۱‬ساختار سطر فرمان‬ ‫در ادامه‪ ،‬ما نیاز به اندکي درك بهتر در اين خصوص داريم که يك فرمان چیست و چگونه توسط مثل تفسیر مي‌شود‪ .‬اين بخش يك‬

‫شمول رسمي‌تر ‪ ،‬با اندکي اطلعات جديد از مبنای شل معرفي شده در فصل اول مي‌باشد‪.‬‬

‫ل نامیدن يك فايل برای اجرا مي‌باشد (بعداً ما انواع ديگری از فرمانها را خواهیم ديد) ‪:‬‬ ‫ساده‌ترين فرمان‪ ،‬تنها يك کلمه است که معمو ً‬ ‫اجرای فايل ‪/bin/Who‬‬

‫‪۰۷:۵۱‬‬ ‫‪۰۸:۳۲‬‬

‫‪۲۸‬‬

‫‪sep‬‬

‫‪tty ۲‬‬

‫‪$who‬‬ ‫‪You‬‬

‫‪۲۸‬‬

‫‪sep‬‬

‫‪tty ۴‬‬

‫‪jpl‬‬ ‫‪$‬‬

‫يك فرمان معمولً با يك سطر جديد پايان مي‌پذيرد‪ ،‬اما يك سمي کالن ؛ نیز يك پايان‌نمای فرمان مي‌باشد ‪:‬‬ ‫‪۱۹۸۳‬‬ ‫‪۱۹۸۳‬‬

‫‪EDT‬‬

‫‪۰۹:۰۷:۱۵‬‬

‫; ‪$ date‬‬ ‫‪web sep ۲۸‬‬

‫‪$ date ; who‬‬ ‫‪web sep ۲۸ ۰۹۷:۲۳ EDT‬‬

‫‪you‬‬ ‫‪tty ۲‬‬ ‫‪sep ۲۸‬‬ ‫‪۰۷:۵۱‬‬ ‫‪jpl‬‬ ‫‪tty ۴‬‬ ‫‪sep ۲۸‬‬ ‫‪۰۸:۳۲‬‬ ‫‪$‬‬ ‫اگر چه سمي کالن‌ها مي‌توانند برای پايان دادن به فرمانها استفاده شوند‪ ،‬اما معمولً تا زماني که شما ‪ RE TV RN‬را تايپ نکنید هیچ‬

‫اتفاقي نمي‌افتد‪ .‬توجه داشته باشید که شل فقط يك پیامواره را پس از فرمانهای متعدد چاپ مي‌کند‪ ،‬اما به جز برای پیامواره ‪،‬‬


‫محیط برنامه سازی لینوکس‬

‫‪63/322‬‬

‫‪$ date ; who‬‬ ‫برابر با تايپ دو فرمان بر روی سطرهای متفاوت مي‌باشد‪ .‬بويژه ‪ who ،‬اجرا نمي‌شود تا زماني که ‪ date‬پايان يافته باشد‪.‬‬

‫ارسال خروجي« ‪ » date ; who‬را درون يك لوله‪ ،‬بررسي کنید ‪:‬‬

‫‪$ date ; who | wc‬‬ ‫‪wed sep ۲۸ ۰۹:۰۸:۴۸ EDT‬‬

‫‪۱۹۸۳‬‬ ‫‪۶۰‬‬

‫‪۲‬‬

‫‪۱۰‬‬

‫‪$‬‬ ‫اين نبايد چیزی باشد که شما انتظار داشتید‪ ،‬چون فقط خروجي ‪ ، who‬وارد ‪ wc‬مي‌شود‪ .‬اتصال ‪ who‬و ‪ wc‬با يك لوله‪ ،‬يك فرمان را‬

‫تشکیل مي‌دهد که خط لوله‌ای نامیده مي‌شود و پس از ‪ ، date‬اجرا مي‌شود‪ .‬حق تقدم | بیشتر از « ; » مي‌باشد‪ ،‬همچنانکه شل سطر‬ ‫فرمان شما را تجزيه مي‌کند‪.‬‬

‫پرانتزها مي‌توانند برای گروه بندی کردن فرمانها استفاده شوند ‪:‬‬

‫‪EDT‬‬

‫‪۱۹۸۳‬‬ ‫‪۰۷:۵۱‬‬

‫‪sep ۲۸‬‬ ‫‪۲۸ ۰۸:۳۲‬‬

‫‪۰۹:۱۱:۰۹‬‬

‫(‪$ )date ; who‬‬ ‫‪wed sep ۲۸‬‬ ‫‪you‬‬

‫‪tty ۲‬‬

‫‪jpl‬‬ ‫‪tty ۴‬‬ ‫‪$ )date ; who( | wc‬‬

‫‪sep‬‬ ‫‪۸۹‬‬

‫‪۳‬‬

‫‪۱۴‬‬

‫خروجیهای ‪ date‬و ‪ ، who‬در يك مسیل منفردی به هم ملحق مي‌شوند که مي‌تواند يك لوله را به پائین ارسال کند‪.‬‬

‫‪$‬‬

‫جريان يافتن داده‌ها درون يك لوله مي‌تواند ضبط شود و در يك فايل (اما نه در يك لولة ديگر) با فرمان ‪ tee‬قرار گیرد‪ ،‬فرماني که‬

‫بخشي از شل نمي‌باشد‪ ،‬اما با اين وجود‪ ،‬قابل استفاده برای لوله‌های انجام عملیات مي‌باشد‪ .‬يك استفاده از آن‪ ،‬ذخیره کردن خروجي‬ ‫واسطه در يك فايل مي‌باشد ‪:‬‬

‫‪)date ; who( | tee save | wc‬‬

‫خروجي از ‪wc‬‬

‫‪۴ ۸۹‬‬ ‫‪۱۹۸۳‬‬

‫‪۲۸ ۰۷:۵۱‬‬

‫‪EDT‬‬

‫‪sep‬‬

‫‪۲۸ ۰۸:۳۲‬‬

‫‪sep‬‬ ‫‪۸۹‬‬

‫‪۳‬‬

‫‪$ cat save‬‬ ‫‪wed sep ۲۸‬‬

‫‪۰۹:۱۳:۲۲‬‬

‫‪tty ۲‬‬

‫‪tty ۴‬‬ ‫‪< save‬‬ ‫‪۱۶‬‬

‫‪$‬‬

‫‪۳‬‬

‫‪wc‬‬

‫‪you‬‬ ‫‪jpl‬‬ ‫‪$‬‬ ‫‪$‬‬

‫‪ tee‬از ورودی خود برای فايل يا فايلهای نامگذاری شده و نیز برای خروجي خود کپي برمي‌دارد‪ ،‬در نتیجه ‪ wc‬همان داده‌ها را دريافت‬

‫مي‌کند‪ ،‬گويا اينکه ‪ tee‬در خط لوله نمي‌باشد‪.‬‬

‫پايان نمای ديگر فرمان‪ ،‬آمپرساند ‪ $‬مي‌باشد‪ .‬اين پايان‌نما‪ ،‬دقیقاً شبیه سمي کالن يا سطر جديد مي‌باشد‪ ،‬به جز اينکه اين علمت به شل‬ ‫مي‌گويد که منتظر کامل شدن فرمان نباشد‪ .‬اساسا ً‪ $ ،‬برای اجرای يك فرمان طولني مدت « در زمینه » استفاده مي‌شود‪ ،‬همچنانکه‬


‫محیط برنامه سازی لینوکس‬

‫‪64/322‬‬

‫شما تايپ فرمانهای محاوره‌ای را ادامه مي‌دهید ‪:‬‬

‫طولني مدت‬

‫فرمان‬

‫‪$ long – running - command‬‬ ‫‪ - id long – running – commend‬پردازش ‪$‬‬ ‫پیامواره سريعاً ظاهر مي‌شود‬

‫‪۵۲۷۳‬‬

‫‪$‬‬

‫با توجه به توانايي برای گروه بندی کردن فرمانها‪ ،‬استفاده‌های جالب ديگری از پردازش‌های زمینه وجود دارد‪ .‬فرمان ‪ ، sleep‬چند ثانیه‬

‫مشخص قبل از خروج‪ ،‬منتظر مي‌ماند ‪:‬‬

‫چنج ثانیه قبل از پیامواره طي مي‌شود‬

‫‪sleep 5‬‬

‫‪$‬‬ ‫‪$‬‬

‫‪$ )sleep 5 ; date( $ date‬‬ ‫‪5278‬‬ ‫‪wed sep 28 09 : 18 : 20 EDT 1983‬‬

‫خروجي ا ز ‪ date‬دوم‬

‫پیامواره ظاهر مي‌شود‪،‬سپس‬

‫‪$ wed sep 28 09 : 18 : 25 EDT 1983‬‬ ‫ثانیه‪ ،‬بعد ًا مي‌آيد ‪date ۵‬‬

‫فرآيند زمینه آغاز مي‌شود‪ ،‬اما سريعاً به خواب مي‌رود؛ در اين میان‪ ،‬فرمان ‪ date‬دوم‪ ،‬زمان جاری و پیامواره‌های شل را برای يك فرمان‬

‫جديد پرينت مي‌کند‪ .‬پنج ثانیه بعد‪ sleep ،‬خارج مي‌شود و اولین ‪ ، date‬زمان جديد را پرينت مي‌کند‪ .‬نشان دادن عبور زمان بر روی‬

‫کاغذ دشوار مي‌باشد‪ ،‬در نتیجه شما بايد اين مثال را بررسي کنید‪( .‬بر اساس اينکه ماشین شما چگونه مشغول است و نیز بر اساس ساير‬ ‫جزئیات ‪ ،‬تفاوت بین دو زمان‪ ،‬ممکن است دقیقاً ‪ 5‬ثانیه نباشد)‪.‬‬

‫اين يك روش آسان برای اجرای يك فرمان در آينده مي‌باشد؛ در نظر بگیريد‬

‫‪$ )sleep 300 ; echo Tea is ready( $ Tea will be ready in smunutes‬‬ ‫‪5291‬‬ ‫‪$‬‬ ‫به عنوان يك مکانیسم باقیمانده قابل استفاده مي‌باشد ‪( .‬يك ‪ ctl-g‬در رشته‪ ،‬که پژواك شده باشد‪ ،‬زنگ پايانه را به صدا در مي‌آورد‬ ‫زماني که پرينت مي‌شود)‪ .‬پرانتزها در اين مثالها لزم هستند‪ ،‬چون حق تقدم ‪ $‬بیشتر از « ; » مي‌باشد‪.‬‬

‫پايان نمای ‪ $‬برای فرمانها بکار مي‌رود و چون خطوط لوله‌ای فرمانها‪ ،‬هستند در نتیجه شمانیاز به پرانتزها برای اجرای خطوط لوله‌ای‬ ‫در زمینه نداريد‪:‬‬

‫‪$ pr file | lpr $‬‬ ‫برای پرينت فايل بر روی چاپگر سطری ترتیب داده مي‌شود بدون اينکه شما را برای خاتمه يافتن فرمان منتظر بگذارد‪ .‬وارد پرانتز کردن‬

‫خط لوله‌ای نیز دارای همین اثر مي‌باشد‪ ،‬اما نیازمند تايپ بیشتر است ‪:‬‬

‫همانند مثال قبل‬

‫‪$‬‬

‫(‪$ )pr file | lpr‬‬

‫اکثر برنامه‌ها‪ ،‬آرگومانها را روی سطر فرمان مي‌پذيرند‪ ،‬مانند فايل (يك آرگومان برای ‪ )pr‬در مثال بال‪ .‬آرگومانها‪ ،‬کلمات هستند‪ ،‬توسط‬


‫محیط برنامه سازی لینوکس‬

‫‪65/322‬‬

‫فاصله‌ها و جدول بنديها از هم جدا مي‌شوند‪ ،‬و اساسا ً فايلهايي را که بايد توسط فرمان پردازش شوند‪ ،‬نامگذاری مي‌کنند‪ ،‬اما آنها‬

‫رشته‌هايي هستند که مي‌توانند به هر روشي که برنامه متناسب به نظر مي‌رسد‪ ،‬تفسیر شوند‪ .‬برای مثال‪ ،pr ،‬اسامي فايلها برای پرينت را‬ ‫مي‌پذيرد‪ ،‬پژواك آرگومانهای خود را بدون تفسیر پژواك مي‌کند و اولین آرگومانـ ‪ grep‬يك نمونه متن را برای جستجو مشخص‬ ‫مي‌کند‪ .‬و البته‪ ،‬اکثر برنامه‌ها نیز دارای انتخابهايي هستند که توسط آرگومانهايي نشان داده مي‌شوند که با علمت منها آغاز مي‌شوند‪.‬‬

‫کاراکترهای متعدد خاص که توسط شل تفسیر مي‌شوند مانند > ‪ ، | ، <،‬؛ و ‪ . $‬آرگومانهای برنامه‌هايي نیستند که شل اجرا مي‌کند‪ .‬در‬

‫عوض آنها‪ ،‬کنترل مي‌کنند‪ .‬که چگونه شل آنها را اجرا مي‌کند‪ .‬برای مثال ‪،‬‬

‫‪$ echo hello > junk‬‬ ‫به ما مي‌گويد که شل‪ ،‬پژواك را تنها با آرگومان ‪ Hello‬اجرا مي‌کند و خروجي را در ‪ junk‬فايل قرار مي‌دهد‪ ، String > junk .‬يك‬ ‫آرگومان برای پژواك نمي‌باشد ؛ بلکه توسط شل تفسیر مي‌شود و هرگز توسط پژواك مشاهده نمي‌شود‪ .‬در حقیقت‪ ،‬اين عبارت نبايد‬

‫آخرين رشته درفرمان باشد ‪:‬‬

‫نیز شبیه به آن مي‌باشد اما کمتر بديهي است‪.‬‬

‫‪$ > junk echo Hello‬‬

‫تمرين ‪ . ۳.۱‬تفاوتهای میان سه فرمان زير چه هستند؟‬

‫‪$ cat file | pr‬‬ ‫‪$ pr < file‬‬ ‫‪$ pr file‬‬ ‫(در طي سالها اپراتور جهت دهي مجدد < ‪ ،‬تا حدودی زمینه خود را برای لوله‌ها از دست داده است؛ به نظر مي‌رسد افراد طبیعتاً بیشتر‬ ‫از « <‪ »file‬به دنبال « ‪ » | cat file‬مي‌باشند‪).‬‬

‫‪ ۳.۲‬فرا كاراكترها‬ ‫شل‪ ،‬تعدادی ديگر از کاراکترهای خاص را تشخیص مي‌دهد؛ و عمومي‌ترين کاراکتر مورد استفاده‪ ،‬کاراکتر ستاره * مي‌باشد که به شل‬ ‫مي‌گويد که به جستجوی فهرست برای اسامي فايلهايي بپردازد که در آنها هر رشته از کاراکترها در موفقیت * رخ مي‌دهد‪ .‬برای مثال‪،‬‬

‫*‪$ echo‬‬ ‫يك پیام نمای ضعیف از ‪ ls‬مي‌باشد‪ .‬چیزی که ما را فصل اول ذکر نکرديم اين است که کاراکترهای تطبیق دهنده نام فايل‪ ،‬به بررسي‬

‫اسامي فايلهايي که با يك نقطه شروع مي‌شوند نمي‌پردازند‪ ،‬و اين به خاطر اجتناب از مشکلت در خصوص اسامي « ‪ » .‬و « ‪» ..‬‬ ‫مي‌باشد که در هر فهرستي وجود دارند‪.‬‬

‫دستور اين است‪ :‬کاراکترهای تطبیق دهندة اسم فايل فقط اسامي فايلهايي را تطبیق دهند که با يك دوره شروع مي‌شوند‪ ،‬اگر دوره‬ ‫آشکارا در نمونه ذخیره مي‌شود‪ .‬به طور معمول‪ ،‬يك ‪ echo‬يا دو ‪ echo‬درست چیزی را که رخ مي‌دهد‪ ،‬شرح مي‌دهند‪:‬‬

‫‪ls$‬‬

‫‪.Proflie‬‬ ‫‪Junk‬‬ ‫‪Temp‬‬ ‫* ‪$ echo‬‬ ‫‪Junk Temp‬‬ ‫* ‪$ echo .‬‬


‫محیط برنامه سازی لینوکس‬

‫‪66/322‬‬

‫‪. .. .profile‬‬ ‫‪$‬‬ ‫کاراکترهای شبیه ستاره * که دارای ويژگیهای خاص مي‌باشند‪ ،‬فراکاراکتر نامیده مي‌شوند‪ .‬تعداد زيادی از آنها وجود دارد‪ :‬جدول ‪۳.۱‬‬

‫يك فهرمست کامل است‪ ،‬اگر چه تعداد کمي از آنها تا فصل ‪ ۵‬مورد بررسي قرار نمي‌گیرند‪.‬‬

‫با توجه به تعداد فراکاراکترها‪‌ ،‬راههايي برای جواب دادن به شکل وجود دارد‪ « ‌ ،‬آن را تنها بگذاريد» ‪ ،‬بهترين و آسانترين راه برای‬

‫حمايت کاراکترهای خاص از تفسیر شدن‪ ،‬ضمیمه کردن آنها در کاراکترهای نقل قولي منفرد مي‌باشد ‪:‬‬

‫'***' ‪$ echo‬‬ ‫***‬ ‫‪$‬‬ ‫همچنین اين امکان وجود دارد که از نقل قولهای دو برابر «‪ »...‬استفاده کنیم‪ ،‬اما شل‪ ،‬حقیقتاً درون اين نقل قولها را برای جستجوی ‪، $‬‬

‫«‪ »...‬و \ مي‌خواند‪ ،‬بنابراين «‪ »...‬استفاده نمي‌کند‪ ،‬مگر اينکه شما قصد پردازش رشتة نقل قول شده را داشته باشید‪.‬‬

‫سومین راه ممکن‪ ،‬قرار دادن يك پس کج خط \ در جلوی هر کاراکتری مي‌باشد که مي‌خواهید آن را از شل محافظت کنید‪ ،‬مانند‬

‫*\*\*\ ‪$ echo‬‬ ‫اگر چه *\*\* ‪ ،‬خیلي انگلیسي نمي‌باشد‪ ،‬اما واژگان شل برای آن‪ ،‬هنوز يك کلمه است که هر رشتة منفردی مي‌باشد که شل آن را به‬ ‫عنوان يك واحد مي‌پذيرد‪ ،‬همراه با فاصله‌ها‪ ،‬البته اگر آنها نقل قول شوند‪.‬‬ ‫نقل قولهای يك نوع ‪‌ ،‬از نقل قولهای نوع ديگر حمايت مي‌کنند‪:‬‬

‫فايل‪‌ ،‬خروجي استاندارد را به فايل هدايت مي‌کند‬

‫''! ‪$ echo '' Don’t do that‬‬ ‫‪Don’t do that‬‬ ‫‪$‬‬ ‫‪$ echo X' * 'y‬‬ ‫‪X*y‬‬ ‫' ‪$ echo '*' A' P‬‬ ‫?‪* A‬‬ ‫‪$‬‬

‫جدول ‪ : ۳.۱‬فراکاراکترهای شل‬

‫فايل‪‌،‬خروجي استاندارد را به فايل ضمیمه مي‌کند‬

‫> ‍ ‪> Prog‬‬ ‫> ‪>> Prog‬‬

‫فايل‪ ،‬ورودی استاندارد را از فايل مي‌گیرد‬

‫< ‍ ‪< Prog‬‬

‫خروجي استاندارد ‪ P1‬را به ورودی استاندارد‬

‫‪| ‍ P2 | P1‬‬

‫ورودی استاندارد تا ‪ Str‬بعدی روی يك خط توسط خودش ‪ :‬سند در اينجا ادامه مي‌يابد‪.‬‬

‫هر رشته از صفر تا چند کاراکتر را در اسامي فايلها تطبیق مي‌دهد‬ ‫هر کاراکتر منفرد را در اسامي فايلها تطبیق مي‌دهد‬

‫هر کاراکتر منفرد را در اسامي فايلها تطبیق مي‌دهد ؛‬

‫‪<<str‬‬ ‫*‬

‫؟‬ ‫[ ‪]ccc‬‬

‫گستره‌هايي شبیه ‪9‬ـ ‪ 0‬يا ‪ a-z‬مجاز هستند‬

‫پايان نمای فرمان ‪ 2P :‬؛ ‪ 1‍P ، 1P‬را انجام دهد و سپس ‪ 2P‬را‪.‬‬

‫;‬


‫محیط برنامه سازی لینوکس‬

‫‪67/322‬‬

‫شبیه ; مي‌باشد‪ ،‬اما تا اتمام ‪ 2P‬منتظر نمي‌ماند‪.‬‬

‫‪$‬‬

‫دستورات را در ‪...‬؛ اجرا مي کند خروجي را جايگزين '‪ '...‬مي‌کند‬

‫' ‪'. . .‬‬

‫دستورات را در ‪ ...‬اجرا مي‌کند‪ ،‬در يك زير شل‬

‫(‪)...‬‬

‫دستورات را در ‪ ...‬اجرا مي‌کند‪ ،‬در شل جاری (به ندرت استفاده مي شود)‬

‫{‪}...‬‬

‫‪ $0 …$4‬توسط آرگومانها برای فايل شل جايگزين مي‌شود‬

‫‪.etc $2 , $1‬‬

‫مقدار متغیر شل ‪var‬‬

‫‪$ var‬‬

‫مقدار ‪ var‬؛ از بي نظمي اجتناب مي‌کند‪ ،‬زماني که به متن‬

‫{‪$}var‬‬

‫محلق مي‌شود ؛ همچنین به جدول ‪ ۵.۳‬مراجعه کنید‪.‬‬

‫‪ \ C‬کاراکتر ‪ C‬را به صورت حرفي مي‌گیرد‪ \ ،‬سطر جديد‪ ،‬حذف مي‌شود‬

‫‪ . . .‬را به صورت حرفي پس از ‪ '. . . ' ، $‬و \ تفسیر شده‪ ،‬مي‌گیرد‪،‬‬

‫\‬

‫« ‪». . .‬‬

‫اگر ‪ #‬کلمه را آغاز کند‪ ،‬مابقي سطر يك توضیح مي‌باشد (در هفتمین‬

‫‪#‬‬

‫ويرايش وجود ندارد)‬

‫به متغیر ‪ var‬نسبت داده مي‌شود‪.‬‬

‫‪Var = value‬‬

‫‪ ; P1‬اجرا مي‌شود‪ ،‬اگر موفق بود‪ ‍P2 ،‬اجرا مي‌شود‬

‫‪ ; P1‬اجرا مي‌شود‪ ،‬اگر ناموفق بود‪ P2 ،‬اجرا مي‌شود‪.‬‬

‫‪P1 $$ P2‬‬ ‫‪P1 | | P2‬‬

‫در مثال اخیر‪‌ ،‬چون نقل قولها‪ ،‬پس از اينکه کار خود را انجام دادند حذف مي‌شوند‪ ،‬در نتیجه ‪ echo‬به صورت يك آرگومان منفرد به‬

‫نظر مي‌رسد که فاقد نقل قول مي‌باشد‪.‬‬

‫رشته‌های نقل قول شده مي‌توانند شامل سطرهای جديد باشند ‪:‬‬

‫‪′ hello‬‬

‫‪$ echo‬‬ ‫‪> world ′‬‬ ‫‪hello‬‬ ‫‪world‬‬ ‫‪$‬‬

‫رشتة « > » يك پیاموارة ثانويه چاپ شده توسط شل مي‌باشد‪ .‬زماني که از شما انتظار مي‌رود که ورودی بیشتری را برای کامل کردن‬ ‫يك فرمان تايپ کنید‪ .‬در اين مثال ‪ :‬نقل قول روی اولین سطر بايد با نقل قول ديگر متوازن شود‪ .‬رشته پیاموارة ثانويه در متغیر ‪ps2‬‬ ‫ذخیره مي‌شود و مي‌تواند بر طبق سلیقه تغییر داده شود‪.‬‬

‫در همة اين مثالها‪ ،‬نقل قول يك فرا کاراکتر‪ ،‬مانع تلش شل برای تفسیر آن مي‌شود‪ .‬فرمان‬

‫‪$ echo x * y‬‬

‫همه اسامي فايلهايي را که با ‪ x‬آغاز و با ‪ y‬پايان مي‌پذيرند‪ ،‬پژواك مي‌کند‪ .‬مثل همیشه‪ ،‬پژواك چیزی در مورد فايلها يا فرا کاراکترهای‬

‫شل نمي‌داند؛ تفسیر * ‪ ،‬اگر وجود داشته باشد‪ ،‬توسل شل ذخیره مي‌شود‪.‬‬

‫چه اتفاقي مي‌افتد‪ ،‬اگر هیچ فايلي با نمونه تطبیق داده نشود؟ شل به جای شکايت کردن (همچنانکه در نسخه‌های قبلي اين کار را انجام‬


‫محیط برنامه سازی لینوکس‬

‫‪68/322‬‬

‫داد)‪ ،‬از رشته عبور مي‌کند‪ ،‬گويا اينکه نقل قول شده است‪ .‬معمول ً اين عقیده بدی است که به اين رفتار تکیه کنیم‪ ،‬اما چنین رفتاری‬

‫مي‌تواند برای يادگیری وجود فايلهايي که يك طرح را تطبیق مي‌کنند‪ ،‬استفاده شود ‪:‬‬

‫فايلهايي وجود ندارد ‪ :‬پیام از ‪lS‬‬ ‫‪xyzzy‬‬

‫وجود مي‌آيد‬

‫فايل ‪، xyzzy‬با ‪x*y‬‬ ‫‪ *، ls‬تفسیر نمي‌کند‬

‫‪$ ls x * y‬‬ ‫يافت نمي شود ‪x * y‬‬ ‫‪$ > xyzzy‬‬

‫تطبیق مي‌شود‬

‫‪$ ls x *y‬‬ ‫‪xy zzy‬‬ ‫‪′x*y′‬‬

‫‪ls‬‬

‫‪$‬‬

‫يافت نمي شود ‪x * y‬‬ ‫‪$‬‬

‫يك پس کج خط در پايان يك سطر‪ ،‬باعث مي‌شود که سطر ادامه يابد؛ و اين يك روش برای نشان دادن يك سطر بسیار طولني در شل‬ ‫مي‌باشد‪.‬‬

‫\ ‪$ echo abc‬‬ ‫\ ‪> def‬‬ ‫‪> ghi‬‬ ‫‪abcdefghi‬‬ ‫‪$‬‬

‫توجه داشته باشید که سطر جديد حذف مي‌شود‪ ،‬زماني که قبل از پس کج خط مي‌آيد‪ ،‬اما زماني که به صورت نقل قول ظاهر مي‌شود‪،‬‬ ‫باقي مي‌ماند‪.‬‬

‫فرا کاراکتر ‪ #‬تقريبا به صورت جهاني برای توضیحات شل استفاده مي‌شود؛ اگر يك کلمه شل با ‪ #‬آغاز شود‪ ،‬ما بقي سطر ناديده گرفته‬ ‫مي‌شود ‪:‬‬

‫‪$ echo hello # there‬‬ ‫‪hello‬‬ ‫‪$ echo hello # there‬‬ ‫‪hello # there‬‬ ‫‪$‬‬ ‫‪ #‬بخشي از هفتمین ويرايش اصلي نبود ‪ ،‬اما عمیق ًا پذيرفته شده است و ما از آن در مابقي کتاب استفاده خواهیم کرد‪.‬‬ ‫تمرين ‪ ۳.۲‬خروجي تهیه شده توسط‬

‫*‪ $ ls .‬را شرح دهید‪.‬‬

‫يك انحراف بر روی پژواك‬

‫اگر چه صراحتاً مورد پي‌گیری واقع نمي‌شود‪ ،‬اما يك سطرج ديد نهايي‪ ،‬توسط پژواك تهیه مي‌شود‪ .‬يك طرح محسوس و شايد تمیزتر‬ ‫برای پژواك‪ ،‬پرينت کردن فقط چیزی است که درخواست مي‌شود‪ .‬چنین چیزی‪ ،‬انتشار پیامواره‌ها را از شل آسان مي‌سازد ‪:‬‬

‫‪ pure - echo Enter $‬يك فرمان ‪:‬‬


‫محیط برنامه سازی لینوکس‬

‫‪69/322‬‬

‫سطر جديد پسین وجود ندارد‬

‫‪ : $‬يك فرمان ‪Enter‬‬

‫اما عیب آن ‪ ،‬اين است که عمومي‌ترين مورد ـ تهیه يك سطر جديد ـ پیش فرض نمي‌باشد و نیاز به تايپ بیشتر دارد ‪:‬‬

‫! ‪$ pure – echo ′Hello‬‬ ‫‪>′‬‬ ‫! ‪Hello‬‬ ‫‪$‬‬ ‫چون يك فرمان بايد با پیش فرض عمومي‌ترين عملکرد استفاده شده خود را اجرا کند‪ ،‬پژواك واقعي‪ ،‬به طور خودکار ضمیمة سطر‬ ‫جديد نهايي مي‌شود‪.‬‬

‫اما اگر مطلوب نباشد چه پیش مي‌آيد؟ هفتمین ويرايش پژواك دارای يك اختیار منفرد‪ – n ،‬و برای حذف آخرين سطر جديد مي‌باشد‬

‫‪:‬‬

‫‪ : $ Enter‬يك فرمان‬

‫‪ :‬يك فرمان ‪echo - n Enter‬‬

‫ـ‬

‫‪$‬‬

‫پیامواره بر روی همان سطر‬ ‫– ‪$ echo‬‬ ‫خاص مي‌باشد ‪ n- ،‬فقط‬

‫‪$‬‬ ‫‪ :‬مي‌باشد که توسط يك سطر جديد دنبال مي‌شود ‪ n-‬تنها مورد دشوار ‪ ،‬پژواك‬ ‫‪$ echo - n′ - n‬‬ ‫‪>′‬‬ ‫‪-n‬‬ ‫‪$‬‬ ‫اين حالت بدترکیب است اما کار مي‌کند و به هر حال اين يك موقعیت نادر است‪ .‬يك روش متفاوت ‪ ،‬ارائه شده در سیستم ‪ ، V‬برای‬ ‫پژواك در خصوص تفسیر ‪ C‬مي‌باشد ـ شبیه توالیهای پس کج خط ‪ ،‬مانند ‪ \ b‬برای پسبرد و ‪( \ c‬که حقیقتا در زبان ‪ c‬نمي‌باشد) برای‬ ‫حذف آخرين سطر جديد ‪:‬‬

‫نسخه سیستم ‪V‬‬

‫‪ : \ C′‬يك فرمان‬

‫‪′ Enter‬‬

‫‪$ echo‬‬ ‫‪ : $‬يك فرمان ‪Enter‬‬

‫اگر چه اين مکانیسم از بي نظمي درخصوص پژواك يك علمت منها اجتناب مي‌کند‪ ،‬اما دارای مشکلت ديگر مي‌باشد‪ .‬پژواك اغلب‬ ‫به عنوان يك راهنمای تشخیص استفاده مي‌شود و پس کج‌خطها توسط تعداد زيادی از برنامه‌هايي تفسیر مي‌شوند که پژواك آنقدر به‬ ‫بررسي آنها مي‌پردازد که به بي‌نظمي اضافه مي‌کند‪.‬‬

‫با اين حال‪ ،‬هر دو طرح پژواك دارای نکات خوب و بد مي‌باشند‪ .‬ما ازهفتمین نسخه ويرايش (‪ )-n‬استفاده مي‌کنیم‪ ،‬بنابراين اگر پژواك‬

‫محلي شما از يك قرارداد متفاوت اطاعت کند‪ ،‬يك جفت از برنامه‌های ما نیاز به تجديد نظر جزئي دارند‪.‬‬

‫پرسش ديگر در خصوص اين نظريه اين است که پژواك چه بايد انجام دهد اگر هیچ آرگوماني ارائه نشود ـ بويژه آيا بايد يك نسخه‬

‫خالي را پرينت کند و يا اينکه اصل چیزی پرينت نکند؟ همه پیاده سازيهای رايج پژواك را که ما مي‌شناسیم‪ ،‬يك سطر خالي پرينت‬

‫مي‌کنند‪ ،‬اما نسخه‌های قبلي چنین کاری را انجام نمي‌دادند و زماني مباحثات زيادی درخصوص اين موضوع وجود داشت‪ .‬داگ‬ ‫مکلروی ‪ ،‬احساسات واقعي عرفاني را در بحث و بررسي خود درخصوص موضوع ارائه داد ‪:‬‬


‫محیط برنامه سازی لینوکس‬

‫‪70/322‬‬

‫يونيكس و پژواك‬ ‫يونیکس در سرزمین نیوجرسي ساکن بود‪ ،‬يك خدمتکار زيبايي که دانشمندان از جاهای دور برای تعريف و تمجید از او مسافرت‬

‫مي‌کردند‪ .‬همه مبهوت از عفت و پاکدامني او‪ ،‬در صدد ازدواج با او بودند‪ ،‬يکي به خاطر زيبايي دخترانة او‪ ،‬ديگری برای فرهنگ آراسته‬

‫او‪ ،‬اما فردی به خاطر زرنگي او درا جرای دقیق وظايفي که به ندرت انجام مي‌شد‪ ،‬حتي در سرزمینهای ثروتمندتر‪ .‬بنابراين قلب پر‬ ‫احساس و خوش برخوردی يونیکس بود که همه خواستگاران غیرقابل تحمل خود را مي‌پذيرفت‪ .‬به زودی بسیاری از فرزندان بزرگ‬

‫شدند و موفق شدند در تمام زمین پخش شدند‪.‬‬

‫طبیعت لبخند زد و مشتاق تر از ساير مخلوقات به يونیکس جواب داد‪ .‬مخلوقات متواضع‌تر که اندکي از رفتارهای آراسته‌تر مي‌دانستند‪،‬‬

‫از پژواك او خوشحال مي‌شدند‪ ،‬بنابراين آنقدر واضح و روشن بود که آنها معتقدند که او مي‌تواند از همان سنگ‌ها و چوبهايي پاسخ‬

‫بشنود که فريادهای آنها را در میان صحرا خراب و مخدوش مي‌کردند‪ .‬و يونیکس مطیع‪ ،‬مجبور به اجرای پژواکهای کامل از هر چیزی‬ ‫بود که از او درخواست مي‌شد‪.‬‬

‫زماني که يك عاشق بي صبر از يونیکس درخواست مي‌کرد «چیزی را پژواك نکن» يونیکس از روی محبت دهانش را باز میکرد‪،‬‬ ‫چیزی را پژواك نمي‌کرد و دوباره دهانش را مي‌بست‪ .‬جوانان به او مي‌گفتند؛ منظور شما چیست که دهانت را اينگونه باز مي‌کني؟ از‬

‫اين به بعد‪ ،‬هرگز دهانت را باز نکن زماني که نمي‌خواهي چیزی را پژواك کني! و يونیکس اطاعت کرد‪.‬‬

‫يك جوان حساس خواهش کرد؛ اما من يك عملکرد کامل مي‌خواهم‪ ،‬حتي وقتي که شما چیزی را پژواك نمي‌کني و پژواکهای کامل‬

‫نمي‌توانند از يك دهان بسته خارج شوند‪ .‬يونیکس نمي‌خواست حتي يك نفر را ناراحت کند و پذيرفت که چیزهای متفاوتي را برای‬ ‫جوان بي صبر و جوان حساس بیان کند‪ .‬او جوان حساس را با « ‪ »\ n‬فرا مي‌خواند‪.‬‬

‫زماني که او« ‪ » \n‬را بیان مي‌کرد‪ ،‬او حقیقتا ً چیزی نمي‌گفت بنابراين بايد دهانش را دوبار باز مي‌کرد يك بار برای گفتن« ‪ »\ n‬و بار‬

‫ديگر برای گفتن هیچ چیزی‪ ،‬و بنابراين او جوان حساس را راضي نکرد و جوان حساس بلفاصله گفت ‪ ،‬صداهای ‪ \n‬يك پژواك کامل‬ ‫برای من هستند اما بار دوم آن را خراب مي‌کند‪ .‬من از تو مي‌خواهم که يکي از آنها را انتخاب کني‪ ،‬بنابراين يونیکس که نمي‌توانست با‬

‫ايجاد دردسر و مزاحمت زندگي کند‪ ،‬موافقت کرد که برخي از پژواکها را از بین ببرد و آن را « ‪ » \ c‬بنامد‪ .‬اکنون جوان حساس‬ ‫مي‌توانست با درخواست« ‪ » \c‬و « ‪ » \n‬با هم‪ ،‬يك پژواك کامل از چیزی داشته باشد‪ .‬اما آنها میگويند که او به خاطر تعداد زياد‬

‫نمادگذاری‌ها فوت کرد‪ ،‬قبل از اينکه او حتي يکي از آنها را بشنود‪.‬‬

‫ل بسنجید‪.‬‬ ‫تمرين ‪ .۳.۳‬پیش‌بیني کنید که کدام يك از فرمانهای ‪ grep‬زير انجام خواهند شد‪ ،‬سپس درك خود را عم ً‬

‫‪grep‬‬ ‫‪grep‬‬ ‫‪grep‬‬ ‫‪grep‬‬ ‫‪grep‬‬

‫‪\$‬‬ ‫‪\\ $‬‬ ‫‪\\\$‬‬ ‫‪′\$′‬‬ ‫‪′\′$′‬‬

‫‪grep‬‬ ‫‪grep‬‬ ‫‪grep‬‬ ‫‪grep‬‬ ‫‪grep‬‬

‫فايلي که حاوی اين فرمانها باشد‪ ،‬يك مورد آزمون خوبي مي‌باشد‪ ،‬اگر شما بخواهید امتحان کنید‪.‬‬

‫\\‬ ‫\\ \\‬ ‫'' \‪'' $‬‬ ‫''' ‪' $‬‬ ‫'' ‪'' $‬‬

‫تمرينـ ‪ . ۳.۴‬شما چگونه به ‪ grep‬مي‌گويید که به جستجوی يك طرحي بپردازد که باـ « ــ » ‪ a‬آغاز مي‌شود؟ چرانقل قول کردن‬


‫محیط برنامه سازی لینوکس‬

‫‪71/322‬‬

‫آرگومان کمك نمي‌کند؟ نکته ‪ :‬در مورد انتخاب ‪C‬ـ تحقیق کنید‪.‬‬

‫تمرين ‪ ۳-۵‬توجه کنید به‬

‫آيا اين فرمان همه اسامي را در همة جهتها تهیه مي‌کند؟ اسامي بر طبق چه نظمي آشکار مي‌شوند؟‬

‫*‪$ echo */‬‬

‫تمرين ‪( ۳-۶‬پرسش راهکار)‪ .‬شما چگونه يك ‪ /‬را در يك اسم فايل قرار مي‌دهید (يعني ‪ ،‬يك ‪ /‬که قطعات مسیر را جدا نمي‌کند)؟‬ ‫تمرين‪ ۳-۷‬با فرمان‬ ‫و با فرمان‬

‫‪$ cat xy / y‬‬ ‫‪$ cat x >> x‬‬

‫چه اتفاقي رخ مي‌دهد؟‬

‫قبل از اينکه به بررسي آنها بپردازيد فکر کنید‪.‬‬

‫تمرين ‪ ۳-۸‬اگر شما فرمان‬

‫* ‪$ rm‬‬

‫را تايپ کنید‪ ،‬چرا ‪ rm‬نمي‌تواند به شما اخطار دهدکه شما در حال حذف همه فايلهای خود هستید؟‬ ‫‪ ۳.۳‬ايجاد فرمانهای جديد‬

‫اکنون وقت آن رسیده است که به سراغ چیزی برويم که در فصل اول قول داديم ـ چگونه فرمانهای جديد را خارج از فرمانهای قبلي‬ ‫ايجاد کنیم‪.‬‬

‫با توجه به يك توالي از فرمانهايي که بیشتر از چندين بار تکرار مي‌شوند‪ ،‬بهتر است که اين توالي را در يك فرمان جديد با نام خودش‬

‫قرار دهیم‪ ،‬در نتیجه شما مي‌توانید از آن به عنوان يك فرمان منظم استفاده کنید‪ .‬برای روشن شدن اين موضوع‪ ،‬فرض کنید که قصد‬

‫شمارش کاربرها را غالب ًا با خط لوله‌ای‬

‫داريد که در فصل اول ذکر شد و شما مي‌خواهید يك برنامه جديد ‪ nu‬را برای انجام آن بوجودآ‌وريد‪.‬‬

‫‪who | wc - 1‬‬

‫‪$‬‬

‫اولین مرحله ايجاد يك فايل معمولي است که شامل '‪ ' who | wc – 1‬مي‌باشد شما مي‌توانید از يك ويراستار مطلوب استفاده کنید و‬

‫يا مي‌توانید از قوه خلقیت استفاده کنید ‪:‬‬

‫‪′ who | wc – 1 ′ > nu‬‬

‫(بدون نقل قولها ‪ ،‬چه چیزی در ‪ nu‬ظاهر مي‌شود؟)‬

‫‪echo‬‬

‫‪$‬‬

‫همانگونه که در فصل اول بیان کرديم ‪ ،‬شل يك برنامه شبیه يك ويراستار يا ‪ who‬و يا ‪ wc‬مي‌باشد؛ و نام آن ‪ sh‬است‪ .‬و چون يك‬

‫برنامه است‪ ،‬شما مي‌توانید آن را اجرا کنید و به ورودی آن مجددا ً جهت دهید‪ .‬بنابراين شل را با ورودی منتج ازفايل ‪ nu‬آن به جای‬

‫پايانه‪ ،‬اجرا کنید‪:‬‬

‫‪tty‬‬ ‫‪tty‬‬ ‫‪tty‬‬

‫‪2 you‬‬ ‫‪4 you‬‬ ‫‪5 you‬‬

‫‪$ who‬‬ ‫‪07:51 28‬‬ ‫‪sep‬‬ ‫‪10:02 28‬‬ ‫‪sep‬‬ ‫‪09:38 28 sep‬‬


‫محیط برنامه سازی لینوکس‬

‫‪72/322‬‬

‫‪you‬‬

‫‪sep‬‬

‫‪4 tty‬‬

‫خروجي شبیه همان چیزی خواهد بود که در هنگام تايپ ‪ who | wc -1‬در پايانه مي‌باشد‪.‬‬

‫‪10:17 28‬‬ ‫‪$ cat na‬‬ ‫‪Who : wc -1‬‬ ‫‪$ sh>nu‬‬ ‫‪4‬‬ ‫‪$‬‬

‫دوباره همانند ساير ـ برنامه‌ها‪ ،‬شل ورودی خود را از يك فايل مي‌گیرد‪ ‌ ،‬اگر فايلي به عنوان يك آرگومان نامگذاری شود ؛ شما‬

‫مي‌توانستید برای رسیدن به همان نتیجه بنويسید‬

‫اما تايپ کردن « ‪ » sh‬در هر مورد‪ ،‬درد سر و زحمت مي‌باشد‪:‬‬

‫چون طولني‌تر است و تمايزی را بین برنامه های نوشته شده در‬

‫‪$ sh nu‬‬ ‫‪ say ،c‬و برنامه‌های نوشته شده از طريق اتصال برنامه‌ها با شل‪‌ ،‬‬

‫بوجود مي‌آورد‪ .‬بنابراين‪ ،‬اگر يك فايل اجراپذير باشد و اگر شامل متن باشد‪ ،‬در نتیجه شل‪ ‌،‬آن را به عنوان يك فايل از فرمانهای شل‬

‫تصور مي‌کند‪ .‬چنین فايلي‌‪ ،‬فايل شل نامیده مي‌شود‪.‬‬

‫همه کاری که شما بايد انجام دهید‪ ،‬اجرا پذيرکردن ‪ nu‬مي‌باشد و در ابتدا‪:‬‬

‫‪$ chomd + x nu‬‬

‫و پس از آن شما مي‌توانید آن را با ‪ ،$ nu‬راه اندازی کنید‪.‬‬

‫از اکنون کاربرهای ‪ nu‬فقط با اجرا کردن آن نمي‌توانند بگويند که شما آن را به اين روش آسان پیاده کنید‪.‬‬

‫روشي که شل حقیقتاً ‪ nu‬را اجرا مي‌کند‪ ،‬ايجاد يك فرآيند جديد شکل دقیق ًا به گونه‌ای که شما ‪ $ sh nu‬را تايپ کرده‌ايد مي‌باشد‪.‬‬

‫اين شل مولود‪ ،‬زير شل نامیده مي‌شود ـ يك فرآيند شلي که توسط شل جاری شما راه‌اندازی مي‌شود‪ ، Shnu .‬همانندـ ‪sh<nu‬‬ ‫نمي‌باشد‪ ،‬چون ورودی استاندارد آن‪ ،‬هنوز متصل به پايانه مي‌باشد‪.‬‬

‫همانگونه که هست‪ nu ،‬فقط زماني که کار مي‌کند که در فهرست جاری شما باشد ( البته مشروط بر اينکه فهرست جاری در مسیر شما‬ ‫باشد‪ ،‬که از حال به بعد ما اينگونه تصور مي‌کنیم)‪ .‬برای ايجاد ‪ nu‬به عنوان بخشي از مجموعه عملکردهای خود‪‌،‬بدون توجه به اينکه‬

‫شما در کدام فهرست قرارداريد‪ ،‬به فهرست ‪ bin‬اختصاصي خود وارد شويد و ‪ / usr/you/bin‬را به مسیر جستجوی خود اضافه کنید‪:‬‬

‫‪$ mkdir bin‬‬

‫‪pwd $‬‬ ‫‪usr/yo u /‬‬ ‫بسازيد اگر قبل اين کار را انجام نداده‌ايد ‪ bin‬يك‬

‫‪echo $ PATH $‬‬ ‫‪asr/you/bin:/bin:/usr/bin /:‬‬ ‫‪mv nu bin $‬‬ ‫‪ nu‬حقیقتاً از فهرست جاری مي‌آيد‬ ‫اما توسط شل يافت مي‌شود‬

‫مسیر را برای اطمینان کنترل کنید‬

‫بايد اينگونه باشد‬

‫را نصب کنید ‪nu‬‬ ‫‪$ ls nu‬‬ ‫يافت نمي‌شود‬ ‫‪$ nu‬‬

‫‪4‬‬ ‫‪$‬‬

‫البته‪ ،‬مسير ‪ PATK‬شما بايد به طور صحيح با برش عرضي ‪ profile‬شما متناسب باشد‪،‬‬


‫محیط برنامه سازی لینوکس‬

‫‪73/322‬‬

‫بنابراين شما نبايد هرزماني كه به سيستم وارد مي‌شويد‪ ،‬آن را ريست سازي كنيد‪.‬‬

‫فرمانهاي ساده ديگري وجود دارند كه شما مي‌توانيد به اين روش براي مناسب كردن‬ ‫محيط خود بر طبق سليقه خود بوجود آوريد‪ .‬برخي از فرمانهايي كه به نظر ما مناسب‬ ‫مي‌باشند‪ ،‬شامل موارد زير هستند‪:‬‬

‫‪ Cs0‬كه توالي صحيح كاراكترهاي مرموز را براي پاك كردن نمايشگر روي پايانه شما پژواك‬ ‫مي كند ( ‪ ۲۴‬سطر جديد يك اجراي كلي مطلوب مي‌باشد)؛‬ ‫‪، What 0‬كه ‪ who‬و ‪ ps - a‬را براي بيان اينكه چه كسي به سيستم وارد مي‌شود و چه كاري‬ ‫انجام مي‌دهد اجرا مي‌كند؛‬ ‫‪ Where 0‬كه شناسايي اسم سيستم يونيكسي را كه شما از آن استفاده مي‌كنيد پرينت‬ ‫مي‌كند ‪ -‬اين فرمان قابل استفاده مي‌باشد اگر شما به طور منظم از آن استفاده كنيد‪( .‬‬ ‫تنظيم ‪ ps1‬نيز به همين منظور مي‌باشد)‪.‬‬

‫تمرينت ‪ . ۳.۹‬بهت تفرمان ‪ / bin,/usr/bin‬مراجعه تكنيد تبراي تاينكه تببينيد تچندت تفرمان تحقيقتًا‬ ‫فايلهاي شل مي‌باشند‪ .‬آيا مي‌توانيد اين كار را با يك فرمان انجام دهيد؟ نكته ‪‌ :‬فايل (‪.)1‬‬

‫حدسيات بر اساس طول فايل چقدر صحيح مي‌باشند؟‬ ‫‪ . ۳.۴‬پارامترها‪ ‬و‪ ‬آرگومانهاي‪ ‬فرمان‪ ‬‬

‫اگر چه ‪ nu‬همانگونه كه هست‪ ،‬مناسب مي‌باشد‪ ،‬اما اكثر برنامه‌هاي شل‪ ،‬آرگومونها را‬ ‫تفسير مي‌كنند‪ ،‬در نتيجه براي مثال‪ ،‬اسامي فايلها و انتخابها مي‌توانند خاص باشند‬ ‫زماني كه برنامه اجرا مي‌شود‪.‬‬

‫فرض كنيد ما مي‌خواهيم برنامه‌اي‌را بسازيم كه ‪ cx‬ناميده مي‌شود براي اينكه حالت يك‬ ‫فايل را براي قابل اجرا شدن تغيير دهيم‪ ،‬بنابراين‬ ‫‪nu $‬‬

‫‪cx‬‬

‫يك صورت مختصر براي‬ ‫‪chomd+xnu $‬‬

‫مي‌باشد‪ ،‬ما به ميزان كافي براي انجام چنين چيزي اطلعات داريم‪ .‬ما به يك فايل با نام‬ ‫‪ cx‬نياز داريم كه محتواي آن‬ ‫‪Chomd + x filename‬‬


‫محیط برنامه سازی لینوکس‬

‫‪74/322‬‬

‫مي‌باشد‪ .‬تنها مورد جديدي كه ما بايد بدانيم اين است كه چگونه بهت ‪ cx‬بگوييم كه نام‬ ‫فايل چيست‪ ،‬چون در هر زماني كه ‪ cx‬اجرا مي‌شود‪ ،‬نام فايل متفاوت است‪.‬‬

‫زماني كه شل‪ ،‬يك فايل از فرمانها را اجرا مي‌كند‪ ،‬هر رخداد از ‪ ،1$‬توسط اولين آرگومان‬ ‫جايگزين مي‌شود‪ ،‬هر ‪ $2‬توسط ‌دومين آرگومان جايگزين مي‌شود و به همين ترتيب تا ‪$9‬‬

‫ادامه مي‌يابد‪ .‬بنابراين اگر فايل ‪ cx‬شامل‬ ‫‪Chomd+x $1‬‬

‫باشد‪ ،‬زماني كه فرمان ت ‪ $ cx nu‬اجرا مي‌شود‪ ،‬زير شل‪،‬ت " ‪ " 1$‬را با اولين آرگومان خود‬ ‫يعني « ‪ » nu‬جايگزين مي‌كند‪.‬‬ ‫اكنون مي‌خواهيم به توالي كل عملكردها نگاهي بيندازيم‪:‬‬

‫‪ Cx‬را به شكل اوليه ايجاد كنيد‬

‫‪>cx‬‬

‫‪ Cx‬را قابل اجرا كنيد‬ ‫يك برنامه آزمايشي ايجاد كنيد‬

‫'‪$ echo chomd + x $1‬‬

‫‪cx‬‬

‫‪$ sh cx‬‬

‫‪$ echo echo Hi, there !>hello‬‬

‫آن را بررسي كنيد‬

‫‪hello‬‬

‫‪$‬‬

‫نمي‌تواند اجرا شود‬

‫‪hello :‬‬

‫آن را قابل اجرا كنيد‬

‫‪$ cx hello‬‬

‫دوباره بررسي كنيد‬

‫‪$ hello‬‬

‫‪ Hi, there! Cx‬را نصب كنيد‬

‫كار مي‌كند‬ ‫‪$ mv CX/urr/you/bin‬‬

‫پاكسازي كنيد‬

‫‪$ rm hello‬‬ ‫‪$‬‬

‫توجه داشته باشيد‬

‫كه ما گفتيم‬ ‫‪$ sh cx cx‬‬ ‫دقیق ًا همانگونه که شل به طور خودکار انجام مي‌داد‪ ،‬اگر ‪ cx‬قابل اجرا بوده و ما تايپ کرديم‬

‫‪$ cx cx‬‬ ‫اگر شما بخواهید با بیش از يك آرگومان کار کنید‪ ،‬چه بايد کرد؟ برای مثال ايجاد برنامه‌ای مانند ‪ cx‬که در يك زمان با چندين فايل کار‬ ‫مي‌کند‪ .‬اولین برش ناقص‪ ،‬قراردادن ‪ ۹‬آرگومان در برنامه شل مي‌باشد‪ ،‬مانند‬

‫‪Chomd+x$l $2 $3 $4 $5 $6 $7 $8 $9‬‬ ‫( اين فرمان فقط تا ‪ $9‬کار مي‌کند‪ ،‬چون رشته ‪ $10‬به صورت اولین آرگومان ‪ 1$‬و”‪ 0‬تجزيه مي‌شود!)‪ .‬اگر کار بر اين فايل شل‪ ،‬کمتر‬

‫از نه آرگومان را فراهم کند‪ ،‬تعداد آرگومانهای مفقوده‪ ،‬رشته‌های تهي هستند؛ تأثیر آن‪ ،‬اين است که فقط آرگومانهايي که حقیقتا ً تهیه‬


‫محیط برنامه سازی لینوکس‬

‫‪75/322‬‬

‫شده‌اند توسط زير شل از ‪ chomd‬عبور مي‌کنند‪ .‬بنابراين اين اجرا کار مي‌کند‪ ،‬اما به طور بديهي کثیف است و خراب مي‌شود‪ ،‬اگر بیش‬ ‫از نه آرگومان تهیه شود‪.‬‬

‫با پیش‌بیني اين برنامه‪ ،‬يك صورت مختصر از * ‪ $‬را فراهم مي‌کند که به معنای «همه آرگومانها» مي‌باشد‪ .‬روش صحیح برای تعريف‬

‫‪ cx‬به صورت * ‪ x chomd + $‬مي‌باشد که بدون توجه به اينکه چند تا آرگومان تهیه مي‌ شوند‪ ،‬کار مي‌کند‪.‬‬ ‫با افزودن* ‪ $‬به مجموعة عملکردهای خود‪ ،‬شما مي‌توانید فايلهای شل مناسبي را تهیه کنید مانند ‪ 1c‬يا ‪: m‬‬

‫‪c:‬‬

‫‪$ cd/usr/you/bin‬‬ ‫‪$ cat 1c‬‬ ‫تعداد سطرها را در فايلها بشماريد‬

‫‪1 #‬‬

‫‪wc -1 * $‬‬ ‫‪$ cat m‬‬ ‫يك روش مختصر برای تايپ پست‬

‫‪: #m‬‬

‫*‪mail $‬‬ ‫‪$‬‬ ‫هر دو مي‌توانند به طور مناسب بدون آرگومانها استفاده شوند‪ .‬اگر هیچ آرگوماني وجود نداشته باشد‪$ * ،‬تهي‌خواهد بود و اصل ً هیچ‬ ‫آرگوماني از ‪ wc‬يا ‪ mail‬عبور نخواهد کرد ‪ .‬با وجود آرگومانها يا بدون آنها‪ ،‬فرمان به طور صحیح راه‌اندازی مي‌شود‪:‬‬

‫* ‪$ 1c / usr / you / bin /‬‬ ‫‪usr / you /bin /cx 1‬‬ ‫‪/ usr /you / bin /1c 2‬‬ ‫‪usr / you / bin / m 2‬‬ ‫‪/ usr / you / bin / nu1‬‬ ‫‪2/ usr / you / bin / what‬‬ ‫‪1 / usr / you / bin / where‬‬ ‫‪9 total‬‬ ‫‪$ 1s /usr/you/bin | 1c‬‬ ‫‪4‬‬ ‫‪$‬‬ ‫اين فرمانها و سايرفرمانها موجود در اين فصل‪ ،‬مثالهايي از برنامه‌های شخصي‪ ،‬نوع چیزهايي که شما برای خود مي‌نويسید و در ‪bin‬‬ ‫خود قرار مي‌دهید‪ ،‬مي‌باشند‪ ،‬اما بعید به نظر مي‌رسد که طورعمومي در دسترس باشند‪ ،‬چون آنها بسیار وابسته به سلیقه شخصي‬

‫مي‌باشند‪ .‬در فصل ‪ ،۵‬ما موضوعات مربوط به نوشتن برنامه‌های شل را که برای استفاده عمومي مناسب مي‌باشند‪ ،‬مورد بحث قرار‬

‫مي‌دهیم‪.‬‬

‫آرگومانها برای يك فايل شل نبايد اسامي فايلها باشند‪ .‬برای مثال‪ ،‬جستجوی يك فهرست راهنمای تلفن شخصي را در نظر بگیريد‪ .‬اگر‬

‫شما دارای فايلي باشید که به صورت ‪ / usr/you/bib/phone-book‬نامگذاری شده باشد و شامل سطرهايي مانند زير باشد‬ ‫‪ 3838‬ت ‪ 976‬ت ‪2‬‬

‫‪dial – a – joke‬‬

‫‪4200‬ت ‪ 246‬ت ‪ial – a – prayer 212‬‬ ‫‪3636‬ت ‪ 976‬ت ‪ial santa 212‬‬ ‫‪ dow Jones report 4141‬ت ‪ 976‬ت ‪212‬‬


‫محیط برنامه سازی لینوکس‬

‫‪76/322‬‬

‫در نتیجه فرمان ‪ grep‬مي‌تواند برای جستجوی آن استفاده شود‪(.‬فهرست ‪ lib‬شما يك مکان خوب برای ذخیره بانك اطلعاتي شخصي‬

‫مي‌باشد)‪ .‬چون ‪ grep‬به فرصت اطلعات اهمیتي نمي‌دهد‪ ،‬شما مي‌تواند به جستجوی اسامي‪ ،‬آدرس‌ها ‪ ،‬رمزهای پستي و يا هر چیزی‬

‫که دوست داريد‪ ،‬بپردازيد‪ .‬مي‌خواهیم يك برنامة فهرست مشارکت بسازيم و آن را به افتخار شماره مشارکت فهرست تلفن جايي که در‬

‫آن زندگي مي‌کنیم ‪ ۴۱۱‬بخوانیم‪:‬‬

‫‪411$ < ' echo 'grep $* /usr/you/lib/phone – book‬‬ ‫‪411$ cx‬‬ ‫‪joke 411 $‬‬ ‫‪ dial - a – joke‬ـ ‪ 976‬ـ ‪3838 212‬‬ ‫‪Dial 411 $‬‬ ‫ـ ‪3838 212 – 976‬‬

‫‪dial - a – joke‬‬ ‫‪dial - a – prayer‬‬ ‫‪dial santa‬‬ ‫در اينجا چیزی اشتباه است‬

‫ـ ‪ 246‬ـ ‪4200 212‬‬ ‫ـ ‪ 976‬ـ ‪3636 212‬‬

‫‪dow jones' 411' $‬‬ ‫‪Grep : can't open jones‬‬

‫نمي‌تواند ‪ jones‬را باز کند‬

‫‪$‬‬

‫مثال آخر شامل نشان دادن يك مشکل پتانسیل مي‌باشد‪ :‬اگر چه ‪ ،jones dow‬برای ‪ ۴۱۱‬به عنوان يك آرگومان مفرد نشان داده مي‌شود‪،‬‬ ‫‌اما شامل يك فضای خالي است و در نقل قولها بزرگتر نمي‌باشد‪ ،‬بنابراين زيرشل‪ ،‬با تفسیر فرمان ‪ ، ۴۱۱‬آن را به دو آرگومان برای‬

‫‪ grep‬تبديل مي‌کند‪ :‬اين فرمان به گونه‌ای است که شما تايپ کرديد‬ ‫و چنین چیزی به طور بديهي اشتباه است‪.‬‬

‫‪grep dow jones /usr/you/lib/phone – book‬‬

‫‪$‬‬

‫يك راه علج‪ ،‬اعتماد به روشي است که شل بر طبق آن‪ ،‬نقل قولهای دوگانه را بررسي مي‌کند‪ .‬اگر چه هر چیزی که با '…' نقل قول‬ ‫مي‌شود‪ ،‬تخطي ناپذير است‪ ،‬اما شل به درون " …" برای ‪ \ 's ،s,$‬و ‪ "… " 's‬نگاه مي‌کند‪ .‬بنابراين اگر شما ‪ ۴۱۱‬را به صورت زير‬

‫تجديد نظر کنید‬

‫‪Grep "$*"/usr/you/lib/phone -book‬‬ ‫•‪ $‬توسط آرگونها جايگزين خواهد شد‪ ،‬اما به عنوان يك آرگومان مفرد از ‪ grep‬عبور خواهد کرد‪ ،‬حتي اگر دارای فاصله‌های خالي‬ ‫باشد‪.‬‬

‫‪212-976-4141‬‬ ‫به راستي‪ ،‬شما مي توانید ‪( grep‬وبنابراين ‪ ) ۴۱۱‬را مستقل از مورد و با انتخاب ‪ y-‬بسازيد‪:‬‬

‫‪dow jones 411 $‬‬ ‫‪dow jones report‬‬

‫…‪$ grep - y pattern‬‬ ‫با ‪ ، -y‬حروف موردی پايین در طرح نیز با حروف موردی باليي در ورودی ‪ ،‬متناسب خواهند بود‪( .‬اين انتخاب در هفتمین ويرايش‬ ‫‪ grep‬وجود دارد‪ ،‬اما در سايرسیستم‌ها وجود ندارد)‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪77/322‬‬

‫چهار نکته در مورد آرگومانهای فرمان وجود دارند که ما تا فصل ‪ ۵‬آنها را ناديده مي‌گیريم‪ ،‬اما يکي از آنها‪ ،‬چیز با ارزشي در اينجا‬ ‫مي‌باشد‪ .‬آرگومان ‪ ،$ 0‬نام برنامه‌ای است که اجرا مي‌شود ـ در ‪ cx ،$0‬به صورت« ‪ » cx‬مي‌باشد‪ .‬يك استفاده جديد از ‪ $0‬در پیاده‬

‫سازی برنامه‌های‪ ۲‬و‪ ۳‬و‪ ۴‬و … مي‌باشد که ورودی خود را در ستونهای زيادی پرينت مي‌کنند‪who | 2 $ :‬‬

‫‪28 21:09‬‬ ‫‪28 22:11‬‬ ‫‪28 19:58‬‬

‫‪tty 5‬‬ ‫‪tty 7‬‬ ‫‪b tty‬‬

‫‪cvw‬‬ ‫‪scj‬‬ ‫‪J1b‬‬

‫‪21:23‬‬ ‫‪22:10‬‬ ‫‪23:00‬‬

‫‪sep‬‬ ‫‪sep‬‬ ‫‪sep‬‬

‫‪28‬‬ ‫‪28‬‬ ‫‪28‬‬

‫‪ttyo‬‬ ‫‪4Tty‬‬ ‫‪ttyg‬‬

‫‪drh‬‬ ‫‪dmr‬‬ ‫‪You‬‬

‫‪$‬‬ ‫پیاده سازيهای ‪ 2‬و ‪ 3‬و … مشابهه هستند؛ و در حقیقت آنها مرتبط به همان فايل هستند‪:‬‬

‫‪ 1n 26‬؛ ‪ 1n 25‬؛ ‪ 1n 24‬؛ ‪1n $ 3 2‬‬ ‫] ‪-1i - $ 1s [9-1‬‬ ‫‪16722‬‬ ‫‪16722‬‬ ‫‪16722‬‬ ‫‪16722‬‬ ‫‪16722‬‬

‫‪28‬‬ ‫‪23:21‬‬ ‫‪2‬‬ ‫‪28‬‬ ‫‪23:21‬‬ ‫‪3‬‬ ‫‪28‬‬ ‫‪23:21‬‬ ‫‪4‬‬ ‫‪28‬‬ ‫‪23:21‬‬ ‫‪5‬‬ ‫‪28‬‬ ‫‪23:21‬‬ ‫‪6‬‬ ‫‪1s/usr/you/bin $ | 5‬‬ ‫‪4‬‬ ‫‪411‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪m‬‬ ‫‪nu‬‬ ‫‪where‬‬ ‫‪what‬‬ ‫‪cat 5‬‬ ‫‪$‬‬ ‫‪ 3 … :‬و ‪ 2‬و‪#‬‬ ‫در ‪ n‬ستون پرينت کنید‬ ‫*‪$‬‬

‫‪5‬‬ ‫‪5‬‬ ‫‪5‬‬ ‫‪5‬‬ ‫‪5‬‬

‫‪-rwxrwxrwx‬‬ ‫‪-rwxrwxrwx‬‬ ‫‪-rwxrwxrwx‬‬ ‫‪-rwxrwxrwx‬‬ ‫‪-rwxrwxrwx‬‬

‫‪you‬‬ ‫‪you‬‬ ‫‪you‬‬ ‫‪you‬‬ ‫‪you‬‬

‫‪3‬‬ ‫‪cx‬‬

‫‪51‬‬ ‫‪51‬‬ ‫‪51‬‬ ‫‪51‬‬ ‫‪51‬‬

‫‪sep‬‬ ‫‪sep‬‬ ‫‪sep‬‬ ‫‪sep‬‬ ‫‪sep‬‬

‫‪2‬‬ ‫‪1c‬‬

‫‪-Pr-$o-t 11‬‬

‫‪$‬‬

‫انتخاب ‪ ،-t‬عنوان را در بالی صفحه خارج مي‌کند و انتخاب ‪ ،-1n‬طول صفحه را تا ‪ n‬سطر تعیین مي کند‪ .‬نام برنامه‪ ،‬تعداد ستونهای‬

‫آرگومان برای ‪ pr‬مي‌شود‪ ،‬در نتیجه خروجي‪ ،‬به صورت يك رديف در يك زمان در تعداد تعداد ستونهای مشخص شده توسط ‪$0‬‬

‫پرينت مي‌ شود‪.‬‬

‫‪ ۳.۵‬خروجي برنامه به صورت آرگومانها‬ ‫اکنون مي‌خواهیم از آرگومانهای فرمان در يك فايل شل به تولید آرگومانها برگرديم‪ .‬مطمئناً گسترش اسم فايل از فراکاراکترهايي شبیه *‬

‫عمومي‌ترين روش برای تولید آرگونها مي‌باشد( غیر از تهیه کردن آنها به صورت آشکارا)‪ ،‬اما روش خوب ديگر از طريق اجرا کردن‬ ‫برنامه‌مي‌باشد‪ .‬خروجي هر برنامه‪ ،‬مي‌تواند با ضمیمه کردن تقاضا در نقل قولهای گذشته '‪ ، ' 1000‬در يك سطر فرمان قرار گیرد‪:‬‬

‫‪$ 'echo at the tone the time will be 'date‬‬ ‫‪19830 EDT 02:15 : 00 29 At the tone the time will be thu sep‬‬ ‫يك تغییر کوچك شرح مي‌دهد که '‪ ' 1000‬درون نقل قول‌های دوگانه « … » تفسیر مي‌شود‪:‬‬

‫‪$ echo ''At the tone‬‬ ‫‪$ ' the time will be 'date ''.‬‬ ‫‪1983 EDT 03:07 : 00 29 The time will be thu sep‬‬


‫محیط برنامه سازی لینوکس‬

‫‪78/322‬‬

‫‪$‬‬ ‫به عنوان مثالي ديگر‪ ،‬فرض کنید شما مي‌خواهید پست الکترونیکي به يك لیست از افرادی بفرستید که اسامي ‪ login‬آنها در فهرست‬ ‫نامه‌رساني فايل وجود دارد‪ .‬يك روش نامناسب برای انجام چنین کاری‪ ،‬ويرايش فهرست نامه رساني در يك فرمان پستي مناسب و‬

‫نشان دادن آن به شل مي‌باشد‪ ،‬اما بسیار راحت‌تر اين است که بگويیم‪.‬‬

‫‪$ mail 'cat mailing list' < letter‬‬ ‫چنین فرمانيـ ‪ cat‬را برای تولید فهرستي از اسامي کاربرها اجرا مي‌کند و اين اسامي آرگومانهايي برای پست مي‌شوند‪( .‬زماني که‬ ‫خروجي درنقل قولهای گذشته به صورت آرگومان تفسیر مي‌شود‪ ،‬شل سطر جديد را به عنوا ن جداساهای کلمه و نه پايان نماهای سطر‬

‫فرمان‪ ،‬بررسي مي‌کند؛ و اين موضوع به طور کامل در فصل ‪ ۵‬مورد بحث و بررسي قرار مي‌گیرد)‪ .‬نقل قولهای گذشته به اندازه کافي‬ ‫برای استفاده آسان مي‌باشند به گونه ای که حقیقتاً نیازی به يك انتخاب فهرست نامه رساني مجزا به فرمان پستي نمي‌باشد‪.‬‬

‫يك روش اندکي متفاوت‪ ،‬تبديل فهرست نامه رساني از يك فهرست از اسامي به برنامه‌ای مي‌باشد که فهرست اسامي را پرينت مي‌کند‪:‬‬

‫‪cat mailing list‬‬

‫اکنون به افرادی که درفهرست هستند نامه ارسال کنید‬

‫‪$‬‬

‫نسخه جديد‬

‫‪echo don whr ejs mb‬‬ ‫‪$ cx mailing list‬‬ ‫‪$ mailing list‬‬ ‫‪don whr ejs mb‬‬ ‫‪$‬‬ ‫‪mail / 'mailing list' < letter‬‬

‫‪$‬‬

‫با افزودن يك برنامه ديگر‪ ،‬حتي تغییرفهرست کاربر به صورت محاوره‌ای امکان‌پذير مي‌باشد‪ .‬برنامه ‪ pick‬نامیده مي‌شود‪:‬‬

‫…‪$ pick arguments‬‬ ‫آرگومانها را در هر زمان يکي‌يکي نشان مي‌دهد و پس از ارائه هر کدام منتظر جواب مي‌ماند‪ .‬خروجي ‪ ،pick‬آرگومانهايي مي‌باشد که‬

‫توسط پاسخهای ‪( y‬برای «بله») انتخاب مي‌شوند؛ و هر پاسخ ديگری باعث مي‌شود که آرگومان حذف شود‪.‬‬

‫برای مثال‪،‬‬

‫‪$ pr 'pick*. C' | pr‬‬ ‫هر اسم فايلي را نشان مي‌دهد که با ‪ ، C‬پايان مي‌پذيرد؛ و اسامي که انتخاب مي‌شوند با ‪ pr‬و ‪ 1pr‬پرينت مي‌شوند ( ‪ pick‬بخشي از‬

‫هفتمین ويرايش نمي‌باشد‪ ،‬اما آنقدر آسان و مفید است که ما نسخه‌های مربوط به آن را در فصل ‪ ۵‬و ‪ ۶‬گنجانده‌ايم‪.‬‬

‫فرض کنید شما دومین نسخه از فهرست نامه‌رساني را داريد‪ .‬سپس‬

‫‪$ mail 'pick\ 'mailing list\ "<letter‬‬ ‫‪don?y‬‬ ‫‪?whr‬‬ ‫‪?ejs‬‬ ‫‪mb?y‬‬ ‫‪$‬‬ ‫نامه را به ‪ don‬و ‪ mb‬مي‌فرستد‪ .‬توجه داشته باشید که نقل قولهای گذشته تو در تو وجود دارند؛ پس کج خطها از تفسیر داخل « … »‬


‫محیط برنامه سازی لینوکس‬

‫‪79/322‬‬

‫در طول تجزيه مورد بیروني‪‌ ،‬جلوگیری مي‌کنند‪.‬‬

‫تمرين ‪ . ۳.۱۰‬اگر پس کج خطها درفرمان ‪$‬‬

‫‪..\ echo 1 'echo\'date‬‬

‫تمرين ‪ 'date' $ . ۳.۱۱‬را بررسي کنید و نتیجه را شرح دهید‪.‬‬

‫تمرين ‪۳.۱۲‬‬

‫‪$ grep -1 pattern filenames‬‬ ‫اسامي فايلهايي را لیست مي‌کند که در آنها يك تطبیق از طرح وجود دارد‪ ،‬اما خروجي ديگری را تولید نمي‌کند‪ .‬برخي از تغییرات را بر‬

‫روی‬

‫‪$ 'command 'grep -1 pattern filenames‬‬

‫بررسي کنید‪.‬‬

‫‪  ۳.۶‬متغيرهاي‪ ‬شل‪ ‬‬ ‫شل‪ ،‬همانند اکثر زبانهای برنامه‌نويسي دارای متغیرهايي مي‌باشد که در زبان حرفه‌ای شل‪ ،‬گاهي اوقات پارامتر نامیده مي‌شوند‪.‬‬

‫رشته‌هايي مانند ‪ ،$1‬پارامترهای مکاني هستند ‪ -‬متغیرهايي که آرگومانها را برای يك فايل شل نگه مي‌دارند‪ .‬رقم موقعیت را در سطر‬

‫فرمان نشان مي‌دهدـ ‪ .‬ماساير متغیرهای شل را نیز ديده‌ايم‪ ، PATH :‬فهرست جهت ها برای جستجوی فرمانها مي‌باشد‪،‬ـ ‪،Home‬‬ ‫فهرست ‪ login‬شما مي‌باشد و به همین ترتیب تا آخر‪ .‬بر خلف متغیرهای موجود در يك زبان منظم‪ ،‬متغیرهای آرگومان نمي‌توانند‬

‫تغییر کنند؛ اگر چه ‪ PATH‬متغیری است که ارزش آن ‪ $ PATH‬مي‌باشد‪ ،‬اما متغیر ‪ ۱‬که ارزش آن ‪ $1‬باشد وجود ندارد‪ ،$1 .‬چیزی‬ ‫بیشتر از يك نماد گذاری فشرده برای اولین آرگومان نمي‌باشد‪.‬‬

‫با کنار گذاشتن پارامترهای مکاني‪ ،‬متغیرهای شل مي‌توانند بوجود آيند‪‌ ،‬وارد شوند و تغییر کنند‪ .‬برای مثال‪،‬‬

‫‪$ PATH = : /bin:/usr/bin‬‬ ‫يك تخصیص مي‌باشد که مسیر جستجو را تغییر مي‌دهد‪ .‬نبايد فضاهای خالي اطراف علمت مساوی وجود داشته باشد و ارزش‬

‫تخصیص يافته بايد يك کلمه مفرد باشد که به اين معنا است که بايد نقل قول شود اگر شامل فرا کاراکترهايي از شل مي‌باشد که نبايد‬ ‫تفسیر شوند‪ .‬ارزش يك متغیر با مقدم واقع شدن يك نام توسط علمت دلر بدست مي‌آيد ‪:‬‬

‫‪$ PATH = $ PATH:/usr/games‬‬ ‫‪$ echo $ PATH‬‬ ‫‪:/usr/you/bin:/bin:/urs/bin/:usr/games‬‬ ‫آن را مجدد ًا ذخیره کنید‬ ‫‪$ PATH=:/usr/you/bin:/bin/usr/bin‬‬

‫‪$‬‬ ‫همه متغیرها برای شل خاص نیستند‪ .‬شما مي‌توانید متغیرهای جديد را با دادن ارزش به آنها ايجاد کنید؛ و به صورت سنتي‪ ،‬متغیرها با‬

‫معني خاص در جعبه باليي تشکیل مي‌شوند و در نتیجه اسامي معمولي در جعبه پائیني قرار دارند‪ .‬يکي از استفاده‌های عمومي از‬ ‫متغیرها‪ ،‬به خاطر آوردن رشته‌های بلند مانند اسامي مسیرها مي‌باشد‪:‬‬

‫‪pwd $‬‬ ‫‪usr/you/bin/‬‬

‫جايي را كه ما بوديم به خاطر آوريد‬

‫‪dir = pwd $‬‬


‫محیط برنامه سازی لینوکس‬

‫‪80/322‬‬

‫به جايي ديگر برويد‬

‫‪$‬‬

‫از متغير در يك اسم فايل استفاده كنيد‬

‫‪cd/usr/mary/bin‬‬ ‫‪$‬‬

‫‪1n $dir/cx‬‬ ‫‌‪…$‬‬

‫براي مدتي كار كنيد‬ ‫برگرديد‬

‫‪cd $dir $‬‬ ‫‪pwd $‬‬ ‫‪usr/you/bin/‬‬ ‫‪$‬‬

‫مجموعه فرمان توکار شل‪ ،‬ارزشهای همه متغیرهای تعريف شده شما را نشان مي‌دهد‪ .‬برای ديدن فقط يك يا دو متغیر‪ ،‬پژواك مناسب‌تر‬

‫است‪.‬‬

‫‪$ set‬‬ ‫‪Home=/usr/you‬‬ ‫=‪IFS‬‬ ‫‪PATH=:/usr/you/bin:/bin:/usr/bin‬‬ ‫‪PS1=$‬‬ ‫>=‪PS2‬‬ ‫‪Dir=/usr/uou/bin‬‬ ‫‪$ echo $dir‬‬ ‫‪/usr/you/bin‬‬ ‫‪$‬‬ ‫ارزش يك متغیر‪ ،‬وابسته به شلي مي‌باشد که آن را بوجود مي‌آورد و به طور خودکار از اولد شل عبور نمي‌کند ‪.‬‬

‫‪ x‬را بوجود آوريد‬

‫‪x = Hello $‬‬

‫مثل جديد‬

‫‪sh $‬‬

‫‪$ echo $ x‬‬

‫فقط سطر جديد ‪ X :‬بدون تعريف در زير شل‬

‫اين شل را ترك کنید‬

‫‪ctl-d $‬‬

‫به شل اولیه برگرديد‬

‫‪$‬‬

‫‪echo $ x‬‬

‫‪ x‬تعريف مي‌شود‬

‫‪Hello‬‬

‫‪$‬‬

‫اين فرمان به اين معناست که فايل شل نمي‌تواند ارزش يك متغیر را تغییر دهد‪ ،‬چون فايل شل توسط يك زير شل اجرا مي‌شود‪:‬‬

‫يك فايل دوسطری ايجاد کنید…‬

‫‪ ......‬برای تعیین و پرينت ‪X‬‬ ‫‪cat setX $‬‬ ‫‪"X="GoodBye‬‬ ‫‪Echo $X‬‬ ‫‪echo $ X $‬‬

‫‪$‬‬

‫‪"X="GoodBye $‬‬ ‫‪> echo $ X" > set X‬‬

‫‪"echo‬‬


‫محیط برنامه سازی لینوکس‬

‫‪81/322‬‬

‫‪ x‬هر شل اوليه‪ ،‬سلم مي‌باشد‬

‫‪Hello‬‬ ‫‪sh setx $‬‬

‫‪ x‬در زير شل خداحافظ مي‌باشد…‬

‫‪Good Bye‬‬ ‫‪echo $ X $‬‬

‫اما هنوز سلم در اين شل مي‌باشد‪Hello                                                   … ‬‬ ‫‪$‬‬ ‫اما زمانهايي وجود دارند که استفاده از يك فايل شل برای تغییر متغیرهای شل مفید مي‌باشد‪ .‬يك مثال بديهي اين است که يك فايل‪،‬‬ ‫يك فهرست جديد به ـ ‪ PATH‬شما اضافه مي‌کند‪ .‬بنابراين شکل يکفرمان « ‪( » .‬نقطه) مي سازد که فرمانها را دريك فايل در شل‬

‫جاری اجرا مي کند‪ ،‬به جای اينکه در زير شل اجرا کند‪ .‬چنین چیزی در ابتدا اختراع شد‪ ،‬در نتیجه افراد مي‌توانستند به طور مناسب‬

‫فايلهای ‪ prfile‬خود را بدون ورود مجدد به سیستم‪ ،‬مجدد ًا اجرا کنند‪ ،‬اما اين اختراع استفاده‌های ديگری نیز دارد‪:‬‬

‫‪$ cat / usr / you / bin / games‬‬ ‫‪PATH= $ PATH : /usr/ games‬‬ ‫‪$ echo $ PATH‬‬ ‫‪:/ usr / you / bin : / bin : / usr / bin‬‬ ‫‪$ . games‬‬ ‫‪$ echo $ PATH‬‬ ‫‪:/ usr / you / bin : / bin : / usr / bin : / usr / games‬‬

‫فايل برای فرمان « ‪ » .‬با مکانیسم ‪ PATH‬جستجو مي‌شود‪ ،‬در نتیجه مي تواند در فهرست ‪ bin‬شما جايگزين شود‪.‬‬

‫زماني که يك فايل با « ‪ » .‬اجرا مي‌شود‪ ،‬فقط به صورت ظاهری شبیه اجرای يك فايل شل مي باشد‪ .‬فايل در مفهوم معمول کلمه اجرا‬

‫نمي شود‪ .‬در عوض‪ ،‬فرمانهای موجود در آن‪ ،‬دقیقاًـ تفسیر مي‌شوند‪ ،‬گويا اينکه شما آنها را به صورت محاوره‌ای تايپ کرده‌ايدـ ‪-‬‬

‫ورودی استاندارد شل موقتاً برای خارج شدن از فايل تغییر مسیر مي‌دهد‪ .‬چون فايل خوانده مي شود اما اجرا نمي‌شود‪ ،‬نبايد مجوزهای‬

‫اجرا داشته باشد‪ .‬تفاوت ديگر اين است که فايل آرگومانهای سطر فرمان را دريافت نمي کند؛ در عوض‪ $1 ،‬و ‪ $2‬و مابقي‪ ،‬خالي‬ ‫هستند‪ .‬اگر آرگومانها عبور مي‌کردند خوب بود‪ ،‬اما آنها عبور نمي‌کنند‪.‬‬

‫روش ديگر برای تعیین ارزش يك متغیر در يك زير شل‪ ،‬نسبت دادن آن به طور آشکارا به سطر فرمان‪ ،‬قبل از خود فرمان مي باشد‪:‬‬ ‫‪echo echo $ x’ > echo x $‬‬ ‫‪CX echo x $‬‬

‫همانند قبل‬

‫‪echox $‬‬

‫ارزش ‪ x‬از زير شل عبور کرد‬

‫‪echo $ x $‬‬ ‫در زير شل تعیین نمي‌شود ‪x‬‬

‫‪Hello‬‬

‫‪x = Hi echo x $‬‬

‫‪Hi‬‬ ‫‪$‬‬

‫(در اصل‪ ،‬نسبت دهي‌ها در هر جايي از سطر فرمان وارد فرمان شدند و اما اين عبور با (‪ dd )۱‬تداخل پیدا کرد)‪.‬‬

‫مکانیسم « ‪» .‬بايد برای تغییر ارزش يك متغیر به طور دائم استفاده شود‪ ،‬در حالیکه نسبت دهي‌های خطي بايد برای تغییرات موقتي‬

‫استفاده شوند‪ .‬به عنوان يك مثال‪ ،‬دوباره جستجوی ‪ usr/games/‬را برای فرمانها با فهرستي که در ‪ PATH‬شما وجود ندارد‪ ،‬در نظر‬


‫محیط برنامه سازی لینوکس‬

‫‪82/322‬‬

‫بگیريد‪:‬‬

‫فرمان بیسکويت شانسي‬

‫‪$ /S / usr / games : grep fort‬‬ ‫‪fortune‬‬

‫يافت نمي‌شود‬

‫‪$ fortune‬‬ ‫‪fortune :‬‬

‫‪$ echo $ PATH‬‬ ‫‪:/ usr / you / bin: / bin: / usr / bin‬‬

‫‪ usr/games‬در ‪ PATH‬وجود ندارد ‪.‬‬

‫‪$ PATH = /usr / games / fortune‬‬ ‫‪.‬شمع را خاموش کنید ؛ کتاب را ببنديد ؛ زنگ را به صدا درآوريد‬ ‫‪$ echo $ PATH‬‬ ‫‪: / usr / you / bin: / bin: / usr / bin‬‬ ‫‪$ cat / usr / you / bin / games‬‬ ‫‪PATH = $ PATH :/ usr / games‬‬ ‫‪$ . games‬‬ ‫‪$ fortune‬‬

‫‪ - Khuth‬بهینه سازی پیش از موقع‪ ،‬ريشة همه مضرات است‬ ‫‪PATH‬‬

‫‪$ echo $ PATH‬‬ ‫در اين زمان تغییر مي‌کند ‪: / usr / you / bin: / bin: / usr / bin: / usr / games‬‬

‫‪$‬‬ ‫استفاده کردن از هر دو مکانیسم دريك فايل شل مفرد‪ ،‬امکان پذير است‪ .‬يك فرمان ‪ games‬اندکي متفاوت مي تواند برای اجرای يك‬ ‫‪ game‬تنها بدون تغییر ‪ PATH‬استفاده شود و يا مي‌تواند ‪ PATH‬رابه طور دائم برای قرار دادن ‪ usr/games/‬تعیین کند‪:‬‬

‫‪* $ PATH = $ PATH : / usr / games‬‬ ‫‪/usr/games‬ندارد‬

‫هنوز وجود ندارد‬ ‫اکنون وجود دارد‬

‫توجه كنيد ‪ *$‬به‬

‫‪$ cat / usr / you / bin / games‬‬

‫‪$ CX / usr / you / bin / games‬‬ ‫‪$ echo $ PATH‬‬ ‫‪:/ usr / you / bin:/ bin: / usr / bin‬‬

‫‪$ games fortane‬‬ ‫‪I'd give my right arm to be ambidextrous.‬‬ ‫‪$ echo $ PATH‬‬ ‫‪:/ usr / you / bin:/ bin:/ usr / bin‬‬ ‫‪$ . games‬‬ ‫‪$ echo $ PATH‬‬ ‫‪:/ usr / you / bin:/ bin:/ usr / bin:/ usr / games‬‬ ‫‪$ for tune‬‬ ‫فردی که ترديد داشت‪ ،‬گاهي اوقات ذخیره مي‌شود‬

‫‪$‬‬ ‫اولین فراخواني برای ‪ ،games‬فايل شل را در يك زير شل اجرا کرد‪ ،‬جايي که ‪ PATH‬به طور موقتي برای ايجاد ‪ usr/games/‬تغییر‬ ‫کرد‪ .‬در عوض دومین مثال‪ ،‬فايل را در شل جاری با *‪ $‬رشتة خالي تغییر کرد‪ ،‬بنابراين فرماني بر روی سطر وجود نداشت و ‪PATH‬‬


‫محیط برنامه سازی لینوکس‬

‫‪83/322‬‬

‫تغییر کرد‪ .‬استفاده از ‪ games‬به اين دو روش دشوار است‪ ،‬اما منجر به يك مسیر ساده مي‌شود که برای استفاده‪ ،‬مناسب و طبیعي است‪.‬‬

‫زماني که شما مي خواهید ارزش يك متغیر را در زير شل‌ها ‪ ،‬قابل دستیابي کنید‪ ،‬از فرمان ‪ export‬شل بايد استفاده شود‪( .‬شما ممکن‬ ‫است فکر کنید که چرا راهي برای صدور ارزش يك متغیر ازيك زيرشل به سقف آن وجود ندارد)‪.‬‬ ‫در اينجا يکي از مثالهای قبلي ما وجود دارد‪ ،‬اکنون با متغیر صادر شده‪:‬‬

‫‪$ x = Hello‬‬ ‫‪$ export x‬‬ ‫‪$ sh‬‬

‫شل جديد‬

‫‪ x‬معروف در زير شل‬ ‫ارزش آن تغییر دهید‬

‫‪$x‬‬

‫‪$ echo‬‬

‫‪Hello‬‬ ‫' ‪$ x = 'Good Bye‬‬

‫از شل خارج شويد‬

‫به شل اولیه برگرديد‬ ‫‪x still Hello‬‬

‫‪$ echo $ x‬‬ ‫‪GoodBye‬‬ ‫‪$ ctl – d‬‬ ‫‪$‬‬ ‫‪$ echo $ x‬‬ ‫‪Hello‬‬ ‫‪$‬‬

‫‪ expor t‬دارای معنای دقیقي مي‌باشد‪ ،‬اماحداقل برای اهداف روزمره‪ ،‬يك دستور ورق زدن‪ ،‬کافي مي‌باشد ؛ مجموعه متغیرهای موقت‬ ‫را برای راحتي کوتاه مدت صادر نکنید‪ ،‬اما همیشه متغیرهايي را صادر کنید که مي‌خواهید در تمام شل‌ها و زير شل‌های خود ست‬ ‫کنید‪( .‬برای مثال شامل شلهايي که با فرمان ! ‪ S’ ed‬آغاز مي‌شوند)‪.‬‬

‫بنابراين‪ ،‬متغیرهايي که برای شل‪ ،‬خاص مي‌باشند‪ ،‬مانند ‪ PATH‬و ‪ ،HOME‬بايد صادر شوند‪.‬‬

‫تمرين ‪ ۳.۱۳‬چرا ما همیشه فهرست جاری را در ‪ PATH‬قرارمي‌دهیم؟ اين فهرست در چه جايي بايد قرار گیرد؟‬ ‫‪ ۳.۷‬مطالبي بیشتر در خصوص جهت دهي مجدد ‪1/0‬‬

‫خطای استاندارد اختراع شد‪ ،‬در نتیجه پیغام‌های خطا همیشه بر روی رايانه ظاهر مي‌شوند‪:‬‬

‫‪diff file 1 file 2 > diff. Out $‬‬ ‫چنین فايل يا فهرستي وجود ندارد‬ ‫‪: diff : file 2‬‬ ‫‪$‬‬

‫مطمئنا ً مطلوب است که پیغام‌های خطا به اين روش کارکنند ـ بسیار ناخوشايند مي‌باشد اگر آنها در ‪ diff . out‬ناپديد شوند و شما با‬

‫اين تصور باشید که فرمان نادرست ‪ diff‬به درستي کار کرده است‪.‬‬

‫هر برنامه دارای سه فايل پیش فرض مي‌باشد که زماني برقرار مي‌شوند که برنامه آغاز مي‌شود‪ ،‬اين سه فايل پیش فرض با اعداد صحیح‬

‫کوچك شماره مي‌گیرند و توصیف گران مي‌شود‪ ،‬اين سه فايل پیش فرض با اعداد صحیح کوچك شماره مي‌گیرند و توصیف گران‬

‫فايل نامیده مي‌شوند (ما در فصل ‪ ۷‬به آنها مراجعه خواهیم کرد) ‪ .‬ورودی استاندارد« ‪ » 0‬و خروجي استاندارد « ‪ » 1‬که ماقبل ً با آنها‬


‫محیط برنامه سازی لینوکس‬

‫‪84/322‬‬

‫آشنا شديم‪ ،‬اغلب از فايلها و لوله‌ها و يا به طرف فايلها و لوله‌ها تغییر جهت مي‌دهند‪ .‬خروجي با شمارة ‪ ، ۲‬يك خروجي خطای‬

‫استاندارد مي‌باشد و در حالت عادی راه خود را به سمت پايانة شما پیدا مي‌کند‪.‬‬

‫گاهي اوقات ‪ ،‬برنامه‌ها‪ ،‬خروجي را بر روی خطای استاندارد تولید مي‌کنند حتي زماني که آنها به درستي کار مي‌کنند‪ .‬يك مثال عمومي‪،‬‬

‫زمان برنامه مي‌باشد که يك فرمان را اجرا مي‌کند و سپس به خطای استاندارد گزارش مي‌دهد که چقدر زمان مي‌گیرد‪.‬‬

‫‪ch 1 . 3‬‬

‫‪2 > time . out‬‬

‫‪$ time wc ch 1 . 3‬‬ ‫‪22691‬‬ ‫‪4288‬‬ ‫‪931‬‬ ‫‪real‬‬ ‫‪0/1‬‬ ‫‪rse‬‬ ‫‪4/0‬‬ ‫‪sys 4/0‬‬

‫‪$ thime wc ch 1 . 3 >wc .out‬‬ ‫‪real‬‬ ‫‪2/0‬‬ ‫‪user‬‬ ‫‪0/4‬‬ ‫‪Sys‬‬ ‫‪0/3‬‬ ‫‪$ time wc ch 3.1 > wc . out‬‬ ‫‪$ cat time – out‬‬ ‫‪1/0‬‬ ‫‪4/0‬‬ ‫‪0/3‬‬

‫‪real‬‬ ‫‪user‬‬ ‫‪sys‬‬ ‫‪$‬‬

‫ساخت ‪( filename >2‬هیچ فاصله‌ای بین ‪ 2‬و > نبايد باشد) خروجي خطای استاندارد را به درون فايل هدايت مي‌کند ؛ اين ساختار از‬

‫نظر نحوی نامناسب است اما کارش را انجام مي‌دهد‪( .‬زمانهای ايجادشده توسط ‪ time‬برای آزمايش کوچکي مانند اين نمونه صحیح‬

‫نمي باشند‪ .‬اما يك توالي از آزمايشات بلندتر‪ ،‬اعداد مفید و به طور معقول قابل اعتماد هستند و شما ممکن است به خوبي بتوانید آنها را‬ ‫برای تحلیل بیشتر ذخیره کنید؛ برای مثال به جدل ‪ ۸.۱‬مراجعه کنید)‪.‬‬

‫همچنین اين امکان وجود دارد که دو مسیل خروجي را در هم ادغام کنیم‪:‬‬

‫‪$ time wc ch 1 . 3 >wc .out‬‬ ‫‪2 >$ 1‬‬ ‫‪$ cat‬‬ ‫‪wc out‬‬ ‫‪22691‬‬ ‫‪4288‬‬ ‫‪931‬‬ ‫‪ch 1 . 3‬‬ ‫‪real‬‬ ‫‪1/0‬‬ ‫‪user‬‬ ‫‪0/4‬‬ ‫‪sys‬‬ ‫‪0/3‬‬ ‫‪$‬‬ ‫نمادگذاری ‪ 2 > $1‬به شل مي‌گويد که خطای استاندارد را بر روی همان مسیل خروجي استاندارد قرار دهد‪ .‬ارزش قابل يادآوری برای‬ ‫آمپرساند وجود ندارد ؛ شیوه‌ای است که به سهولت بايد آموخته شود‪ .‬شما نیزمي‌توانید از ‪ 1> $2‬برای افزودن خروجي استاندارد به‬

‫خطای استاندارد استفاده کنید‪:‬‬

‫‪Echo … 1 > $2‬‬


‫محیط برنامه سازی لینوکس‬

‫‪85/322‬‬

‫بر روی خطای استاندارد پرينت مي‌کند‪ .‬در فايلهای شل‪ ،‬اين فرمان از ناپديد شدن پیغامها درون يك لوله يا درون فايل به طور تصادفي‬ ‫‪ ،‬جلوگیری مي‌کند‪.‬‬

‫شل مکانیسمي را بوجود مي آورد که بواسطه آن شما مي‌توانید ورودی استاندارد را برای يك فرمان‪ ،‬در طول دستور قرار دهید‪ ،‬به جای‬ ‫اينکه بر روی يك فايل جداگانه بگذاريد‪ .‬در نتیجه فايل شل مي‌تواند به طور کامل همه چیز را در خود داشته باشد‪ .‬برنامة اطلعات‬

‫فهرست ما ‪ ،۴۱۱ ،‬مي‌تواند به اين صورت نوشته شود‪:‬‬

‫‪$ cat 411‬‬ ‫‪grep "$ *" << End‬‬ ‫ـ ‪ 976‬ـ ‪dial – a – joke 3838 -212‬‬

‫ـ ‪ 246‬ـ ‪dial – a – prayer 4200 -212‬‬ ‫ـ ‪ 976‬ـ ‪dial santa 3636 212‬‬

‫ـ ‪ 976‬ـ ‪dow jones report 4141-121‬‬

‫‪End‬‬ ‫‪$‬‬ ‫جارگن شل برای اين ساختار‪ ،‬يك سند در اينجا‪ ،‬مي‌باشد؛ به اين معنا که ورودی در اينجا صحیح است به جای اينکه دريك فايل در‬

‫جای ديگر باشد‪ ، << .‬به ساختار‪ ،‬علمت مي‌دهند؛ کلمه‌ای که دنبال مي‌شود (کلمة ‪ End‬در مثال ما) ‪ ،‬برای مجزا ساختن ورودی‬

‫استفاده مي‌شود‪ ،‬که به عنوان هر چیزی برای رخداد اين کلمه روی يك سطر توسط خودش‪ ،‬پذيرفته مي‌شود‪ .‬شل برای ‪ '…' ، $‬و ‪،1‬‬ ‫دريك سند در اينجا‪ ،‬جايگزين مي‌کند‪ ،‬مگر اينکه بخشي از کلمه با نقل قولها يا يك پس کج خط ‪ ،‬نقل قول شود؛ در اين مورد‪ ،‬کل‬

‫سند‪ ،‬به صورت حرفي مي‌شود‪.‬‬

‫ما به موضوع اسناد در اينجا‪ ،‬در پايان فصل‪ ،‬با يك مثال جالب تر مراجعه مي‌کنیم‪.‬‬

‫جدول ‪ . ۳.۲‬جهت دهي های مجدد و متعدد ورودی ـ خروجي را که شل آنها را درك مي‌کند‪ ،‬لیست مي‌کند‪.‬‬

‫تمرين ‪ . ۳.۱۴‬نسخة سند در اينجای ‪ ۴۱۱‬را با نسخة اصلي مقايسه کنید‪ .‬کدام يك راحتتر قابل نگهداری است؟ کدام يك مبنای بهتری‬ ‫برای يك سرويس کلي مي‌باشد؟‬

‫جدول ‪ :۳.۲‬جهت دهي های مجدد ‪ I/O‬در شل‬

‫خروجي استاندارد رابه سمت فايل هدايت مي‌کند‬ ‫خروجي استاندارد رابه فايل پیوست مي‌کند‬ ‫>‪file‬‬

‫<‪file‬‬

‫<< ‪ file‬ورودی استاندارد را از فايل مي‌گیرد‬

‫خروجي استاندارد برنامة ‪ 1P‬را به ورودي ‪ 2P‬متصل مي‌كند‬ ‫مترادف را براي | خارج مي‌كند‬ ‫خروجي را از توصیفگر فايل ‪ n‬به فايل هدايت مي‌کند‬

‫خروجي را از توصیفگر فايل ‪ n‬به فايل پیوست مي کند‬

‫خروجي توصیفگر فايل ‪ n‬را در توصیفگر فايل ‪ m‬ادغام مي‌کند‬

‫‪n>file‬‬ ‫‪n>>file‬‬ ‫‪n>$ m‬‬

‫‪P. | P‬‬ ‫∧‬

‫‪2‬‬


‫محیط برنامه سازی لینوکس‬

‫‪86/322‬‬

‫ورودی توصیفگر فايل ‪ n‬را در توصیفگر فايل ‪ m‬ادغام مي‌کند‬

‫سند در اينجا‪ :‬ورودی استاندارد را مي‌گیرد‪ ،‬تا زمان ‪ S‬بعدی‬

‫‪n<$m‬‬ ‫>>‪S‬‬

‫در آغاز يك سطر ؛ آن را جايگزين ‪ '…' ، $‬و ‪ 1‬مي‌کند‬

‫سند در اينجا بدون جايگزيني‬

‫‪>> S1‬‬

‫سند در اينجا بدون جايگزيني‬

‫'‪>> 'S‬‬

‫‪ ۳.۸‬حلقه سازي در برنامه‌هاي شل‬ ‫شل‪ ،‬حقیقتا ً يك زبان برنامه نويسي مي‌باشد‪ :‬شل دارای متغیرها‪ ،‬حلقه‌ها‪ ،‬تصمیم‌گیری و مواردی از اين قبیل مي‌باشد‪ .‬ما در اينجا به‬ ‫بحث و بررسي درخصوص حلقه سازی اساسي مي‌پردازيم و درخصوص روند کنترل در فصل ‪ ۵‬صحبت مي‌کنیم‪.‬‬

‫حلقه‌ای کردن يك مجموعه از اسامي فايلها‪ ،‬بسیار عمومي است و بیان ‪ for‬شل‪ ،‬تنها بیان روند کنترل شل مي‌باشد که عموما ً بايد در‬

‫پايانه تايپ شود به جای اينکه در يك فايل يا دراجرای بعدی قرار گیرد‪ .‬نمو عبارت است از‪:‬‬

‫‪for var in listof wrds‬‬ ‫‪do‬‬ ‫‪commands‬‬ ‫‪done‬‬ ‫برای مثال‪ ،‬يك بیان ‪ for‬برای پژواك اسامي فايل ها در هر سطر به اين صورت است‪.‬‬

‫* ‪$ for I in‬‬ ‫‪> do‬‬ ‫>‬ ‫‪echo $ i‬‬ ‫‪> done‬‬

‫«‪ »i‬مي‌تواند هر متغیری از شل باشد‪ ،‬اگرچه ‪ ، i‬قديمي است‪ .‬توجه داشته باشید که ارزش متغیر‪ ،‬توسط ‪ i$‬ارزيابي مي‌شود‪ ،‬اما ارزش‬ ‫حلقه‪ ،‬به متغیربه صورت ‪ ، i‬نسبت داده مي‌شود‪ .‬ما از * برای جمع کردن همة فايلها در فهرست جاری استفاد کرديم‪ ،‬اما از هر فهرست‬

‫ديگری از آرگومانها مي‌توان استفاده کرد‪ .‬درحالت عادی ‪ ،‬شما مي‌خواهید چیزی جالبتر از صرفاً پرينت کردن اسامي فايلها انجام دهید‪.‬‬

‫چیزی که ما غالبا ً انجام مي‌دهیم‪ ،‬مقايسه کردن يك مجموعه از فايلها با نسخه‌های قبلي مي‌باشد برای مثال‪ ،‬برای مقايسة نسخة قبلي‬

‫فصل ‪( ۲‬حفظ شده در فهرست قبلي) با نسخة فعلي‪:‬‬

‫‪$ 1S ch2 . * | 5‬‬ ‫‪ch1 . 2‬‬ ‫‪ch2 . 2‬‬ ‫‪ch3 . 2‬‬ ‫‪ch4 . 2‬‬ ‫‪ch5 . 2‬‬ ‫‪ch6. 2‬‬ ‫‪ch 7. 2‬‬ ‫*‪$ for i in ch2.‬‬ ‫‪> do‬‬ ‫>‬ ‫‪echo $ i:‬‬ ‫>‬ ‫‪diff – b old / $ i $ i‬‬ ‫>‬ ‫‪echo‬‬ ‫يك سطر خالي برای قابلیت خواندن اضافه کنید‬


‫محیط برنامه سازی لینوکس‬

‫‪87/322‬‬

‫‪> don | pr - h "diff 'pwd' / old 'pwd' " | lpr $‬‬ ‫‪3712‬‬ ‫‪process -id‬‬ ‫‪$‬‬ ‫ما خروجي را به ‪ pr‬و ‪ lpr‬از طريق لوله متصل کرديم برای اينکه شرح دهیم اين امکان وجود دارد که‪ :‬خروجي استاندارد برنامه‌ها در‬

‫يك ‪ ، for‬وارد خروجي استاندارد خود ‪ for‬شود‪ .‬ما يك عنوان خیالي را با انتخاب ‪ - h‬از ‪ ،pr‬بر روی خروجي قرار مي‌دهیم و از دو‬

‫فراخواني توکار ‪ pwd‬استفاده مي‌کنیم‪ .‬و ما کل توالي را طوری ست مي‌کنیم که به طور ناهمگام (‪ )$‬اجرا شود‪ ،‬در نتیجه ما نبايد برای‬

‫اجرای آن صبر کنیم ؛ ‪ $‬برای تمام حلقه و خط لوله‌ای بکار مي‌رود‪.‬‬

‫ما ترجیح مي‌دهیم که يك بیان ‪ for‬رافرمت کنیم‪ ،‬همانگونه که نشان داده مي‌شود‪ ،‬اما شما مي‌توانید از اندازه‌ای آن را متراکم کنید ‪.‬‬

‫محدوديتهای مهم‪ do ،‬و ‪ done‬مي‌باشند که فقط به عنوان لغات کلیدی شناخته مي‌شوند‪ ،‬زماني که دقیقاً پس از يك سطر جديد يا سمي‬

‫کالن ظاهر مي‌شوند‪ .‬براساس اندازة ‪ for‬گاهي اوقات بهتر است که آن را تمام ًا روی يك سطر بنويسیم‪:‬‬

‫‪for i in list ; do commands ; done‬‬ ‫شما بايد از حلقة ‪ for‬برای فرمانهای متعدد و يا در جايي استفاده کنید که پردازش آرگومان توکار در فرمانهای منفرد‪ ،‬مناسب نمي‌باشد ‪.‬‬ ‫اما از آن‪ ،‬زماني که فرمان منفرد‪ ،‬اسامي فايلها را حلقه سازی مي‌کند‪ ،‬استفاده نکنید‪:‬‬

‫اين فرمان پائین تر از فرمان زير مي‌باشد‪:‬‬

‫‪# poor idea:‬‬ ‫* ‪for I in $‬‬ ‫‪do‬‬ ‫‪< homd +× $I‬‬ ‫‪done‬‬

‫‪* $ × + Chomd‬‬ ‫چون حلقة ‪ for‬يك ‪ chomd‬مجزارا برای هر فايل اجرا مي‌کند‪ ،‬که در دستگاههای کامپیوتر پرهزينه‌تر مي‌باشد ‪ ( .‬اما اطمینان داشته‬

‫باشید که شما تفاوت بین‬

‫‪* for i in‬‬

‫را که همة اسامي فايلها را دريك فهرست جاری حلقه بندی مي‌کند و‬

‫‪* $ for i in‬‬

‫را که همة آرگومانها را برای فايل شل حلقه‌بندی مي‌کند‪ ،‬درك مي‌کنید)‪.‬‬

‫فهرست آرگومان برای يك ‪ ، for‬اغلب از طرحي مي‌آيد که منطبق با اسامي فايلها مي‌باشد اما مي‌تواند از هر جای ديگری نیز بیايد‪ .‬اين‬ ‫فهرست مي‌تو‬

‫' ‪$ for i in 'cat ....‬‬ ‫باشد و يا ارگومانها نمي توانند تايپ شوند‪ .‬برای مثال‪ ،‬قبل در اين فصل ما يك گروه از برنامه ها را برای پرينت چند ستوني‪ ،‬با عناوين‬

‫‪۲‬و‪۳ .‬و از اين قبیل بوجود آورديم‪ .‬اين موارد خطوط پیوند به يك فايل تنها مي باشند که مي تواند ساخته شود‪ ،‬زماني که فايل ‪ ۲‬به اين‬

‫صورت نوشته مي شود‪:‬‬

‫‪for i in‬‬

‫‪Done ; $I 2 in do ; 6 5 4 3 $‬‬ ‫‪$‬‬

‫به عنوان يك استفادة تاحدودی جالب‌تر از ‪ for‬ما مي‌توانیم از ‪ pick‬استفاده کنیم برای اينکه انتخاب کنیم کدام فايلها را با ساير فايلهای‬ ‫موجود در فهرست پشتیبان مقايسه کنیم‪:‬‬

‫' *‪for i in 'pick ch2.‬‬

‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪88/322‬‬

‫‪> do‬‬ ‫>‬ ‫‪echo $i:‬‬ ‫>‬ ‫‪diff old / $ i $i‬‬ ‫‪> done | pr | lpr‬‬ ‫‪chr. 1 ? y‬‬ ‫؟ ‪ch2 . 2‬‬ ‫؟ ‪ch 3 . 2‬‬

‫‪ y‬؟ ‪ch 4 . 2‬‬ ‫‪y‬؟ ‪ch 5 . 2‬‬ ‫؟ ‪ch 6 . 2‬‬

‫؟‬

‫‪ch7 . 2‬‬

‫‪$‬‬ ‫بديهي است که اين حلقه بايد برای تايپ زمان بعدی در يك فايل شل قرار داده شود‪ :‬اگر شما چیزی را برای دوبار انجام داده‌ايد‪ ،‬اين‬ ‫احتمال وجود دارد که شما دوباره آن را انجام دهید‪.‬‬

‫تمرين ‪ ۳.۱۵‬اگر حلقة ‪ diff‬دريك فايل شل قرار داده شود‪ ،‬آيا شما ‪ pick‬را در فايل شل قرار مي‌دهید؟ چرا بله و چرا نه؟‬ ‫تمرين ‪ ۳.۱۶‬چه اتفاقي مي‌افتد اگر سطر آخر حلقة بال به اين صورت باشد‪.‬‬ ‫يعني اينکه با يك آمپرساند پايان پذيرد؟ ببینید آيا مي‌توانید از آن سردر بیاوريد‪ ،‬سپس آن را بررسي کنید‪.‬‬

‫‪> done | pr | 'pr $‬‬

‫‪ ۳.۹‬بسته ‪ :‬يكي كردن همه آنها‬ ‫برای اينکه بدانیم چگونه فايلهای شل گسترش مي‌يابند‪ ،‬با يك مثال بزرگتر کار مي‌کنیم‪ .‬تصور کنید که پستي را از يك دوست از‬

‫دستگاهي ديگردريافت کرده‌ايد‪ ،‬که مي‌گويد ‪ somewhere!bob‬و يعني اينکه او مي‌خواهد کپي‌هايي از فايلهای شل در ‪ bin‬شما را‬ ‫داشته باشد‪ .‬ساده‌ترين راه برای فرستادن آنها‪ ،‬برگرداندن پست است‪ ،‬بنابراين شما با تايپ زير آغاز کنید‪:‬‬

‫‪$ cd /usr/you/bin‬‬ ‫'*‪$ for i in 'pick‬‬ ‫‪> do‬‬ ‫>‬ ‫= = = = = = = =اين هست فايل ‪echo = = = = = = = = = = = = = =$i‬‬

‫>‬ ‫‪cat $i‬‬ ‫‪> done | mail /‬‬ ‫‪somewhere ! bob‬‬ ‫‪$‬‬ ‫اما از نقطه نظر ‪ somewhere ! bob‬به آن نگاه کنید‪ :‬او قصد دارد که يك پیغام پستي با همة فايلهايي که به وضوح مرزنمايي مي‬

‫شوند‪ ،‬دريافت کند ‪ ،‬اما او بايد از يك ويراستار برای تبديل کردن آنها به فايلهای جزء استفاده کند ‪ .‬علمت دريافت اين است که يك‬

‫پیغام پستي به طور صحیح ساخته شده بتواند به طور اتوماتیك خود را باز کند‪ ،‬در نتیجه گیرنده نبايد کاری انجام دهد‪ .‬چنین چیزی دال‬ ‫بر اين است که يك فايل شل بايد حاوی هردو فايل و دستورالعملهايي برای بازکردن آن باشد‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪89/322‬‬

‫دومین دريافت اين است که اسناد در اينجای شل‪ ،‬يك روش مناسب برای ترکیب يك درخواست فرمان و داده‌های فرمان باشند‪ .‬مابقي‬

‫کار‪ ،‬فقط گرفتن نقل قولها به طور صحیح مي‌باشد‪ .‬در اينجا يك برنامة کاربا عنوان ‪ bundle‬وجود دارد که فايلها را در يك فايل شل‬ ‫خود توضیح بر روی خروجي استاندارد آن‪ ،‬گروه‌بندی مي‌کند‪:‬‬

‫‪$‬‬ ‫‪cat bundle‬‬ ‫‪#‬‬ ‫‪bundle : group filles into distribution package‬‬ ‫'‪echo '# To unbundle , sh this file‬‬ ‫‪for i‬‬ ‫‪do‬‬ ‫"‪echo "echo $i 1>$2‬‬ ‫"'‪echo "cat >>ii << 'End of $ i‬‬ ‫‪cat $i‬‬ ‫"‪echo "End of $i‬‬ ‫‪done‬‬ ‫‪$‬‬ ‫نقل قول کردن « ‪ »End of $i‬اطمینان مي‌دهد که همة فراکاراکترهای شل در فايلهای ناديده گرفته مي‌شوند‪.‬‬ ‫در حالت طبیعي‪ ،‬شما بايد قبل از وارد کردن آن بر روی ‪ ، somewhere 1bob‬آن را بررسي کنید‪:‬‬

‫‪$ bundle CX 1C > junk‬‬ ‫‪$ cat junk‬‬ ‫‪# To unbundle , sh this file‬‬ ‫‪echo CX 1>$ 2‬‬ ‫'‪cat SCX <<'End of CX‬‬ ‫*‪chomd +× $‬‬ ‫‪End of CX‬‬ ‫‪Echo 1C 1>$2‬‬ ‫'‪Cat >1C <<'End of 1C‬‬ ‫‪# 1C : count numbr of lines in files‬‬ ‫*‪ $‬ـ ‪wc 1‬‬

‫‪Try it out‬‬

‫‪looks good‬‬

‫‪End of 1C‬‬ ‫‪$‬‬ ‫‪mkdir test‬‬ ‫‪$‬‬ ‫‪cd test‬‬ ‫‪$‬‬ ‫‪sh .. / junk‬‬ ‫‪cx‬‬ ‫‪1c‬‬ ‫‪$ 1S‬‬ ‫‪cx‬‬ ‫‪1c‬‬

‫‪$ cat CX‬‬ ‫*‪chomd +× $‬‬ ‫‪$ cat 1C‬‬ ‫‪# 1C : count number of lines infiles‬‬ ‫*‪ $‬ـ ‪wc 1‬‬ ‫‪$ cd ..‬‬


‫محیط برنامه سازی لینوکس‬

‫‪90/322‬‬

‫‪clean up‬‬ ‫‪send the files‬‬

‫‪$ rm junk test /*; rmdir test‬‬ ‫‪$ pwd‬‬ ‫‪/usr/you/bin‬‬ ‫‪$ bundle 'pick * '| mail / somewhere !bob‬‬

‫اگر يکي از فايلهايي که شما مي‌فرستید برحسب اتفاق دارای يك سطر به شکل زير باشد‪:‬‬

‫‪End of filename‬‬ ‫مشکل وجود دارد‪ ،‬اما اين يك اتفاق با احتمال بسیار پائین مي‌باشد‪ .‬برای ايجاد يك بستة صرفا ً امن ‪ ،‬ما نیاز به يك يا دو مورد از‬

‫فصلهای بعدی داريم‪ ،‬اما چنین چیزی به طور قابل توجهي‪ ،‬قابل استفاده و مناسب مي‌باشد ‪ ،‬همانگونه که نشان مي‌دهد‪.‬‬

‫‪ ، bundle‬تغییرپذيری محیط يونیکس را شرح مي‌دهد نه ‪ bundle‬از حلقه‌های شل‪ ،‬جهت دهي مجدد ‪ ، I/O‬اسناد موجود در اينجا و‬

‫فايلهای شل استفاده مي‌کند‪bundle.‬مستقیماً با پست (‪ )mail‬ارتباط برقرار مي‌کند و شايد به طور جالب‌تر‪ ،‬برنامه‌ای است که يك برنامه‬

‫را بوجود مي آورد‪ ،bundle .‬يکي از بهترين برنامه‌های شل مي‌باشد که ما مي‌شناسیم ‪ -‬سطرهای اندکي از رمز که هرچیزی را ساده‪،‬‬ ‫مفید و دقیق انجام مي‌دهند‪.‬‬

‫تمرين ‪ .۳.۱۷‬شما چگونه از ‪ bunddle‬برای فرستادن همة فايلها دريك فهرست و زيرفهرست‌های آن استفاده مي‌کنید؟ توجه‪ :‬فايلهای‬

‫شل مي‌توانند بازگشتي باشند‪.‬‬

‫تمرين ‪ bunddle .۳.۱۸‬را به گونه‌ای تغییر دهید که با هر فايل حاوی اطلعات ذخیره شده از ‪1‬ـ ‪ ، S1‬بويژه موارد مجاز و زمان آخرين‬ ‫تغییر باشد‪ .‬تسهیلت ‪ bunddle‬رابا برنامة بايگاني ‪ ar‬مقايسه کنید‪.‬‬

‫‪ ۳.۱۰‬چرا يك شل قابل برنامه ريزي‬ ‫شل يونیکس‪ ،‬نمونة مفسران فرمان نمي‌باشد‪ :‬اگرچه اين امکان رابه شما مي‌دهد که فرمانها را در روش معمول اجرا کنید اما چون يك‬ ‫زبان برنامه‌نويسي است‪ ،‬مي‌تواند کارهای بیشتری انجام دهد‪ .‬ارزش آن تا حدودی به چیزی برمي‌گردد که ما در آن مشاهده کرده‌ايم‪،‬‬

‫تاحدودی به اين دلیل که مطالب زيادی در اين فصل وجود دارد‪ ،‬اما بیشتر به خاطر اينکه ما قول داديم که درخصوص «ويژگیهای‬ ‫عموماً استفاده شده» صحبت کنیم و سپس حدود ‪ ۳۰‬صفحه در خصوص مثالتي مربوط به برنامه ريزی شل نوشتیم‪.‬‬

‫اما زماني که شما از شل استفاده مي‌کنید‪ ،‬شما در تمام مدت‪ ،‬مطالب اندکي درخصوص برنامه‌های يك سطری مي‌نويسید ‪ :‬يك خط‬ ‫لوله‌ای‪ ،‬يك برنامه است همانند اين مثال که «چای حاضراست»‪ .‬شل به اين صورت کار مي‌کند‪ :‬شما به طور مداوم به آن برنامه‬

‫مي‌دهید‪ ،‬اما بسیار آسان و طبیعي است (همانگونه که شما با آن آشنا هستید) بطوری که شما نمي توانید به عنوان يك زبان برنامه‌نويسي‬

‫به آن فکر کنید‪.‬‬

‫شل بعضي از کارها را انجام مي‌دهد‪ ،‬مانند حلقه سازی‪ ،‬جهت دهي مجدد ‪ I/O‬با دو > و < گسترش اسم فايل با * ‪ ،‬بنابراين هیچ‬ ‫برنامه‌ای نگران اين کارها نمي‌باشد و به طور مهمتر‪ ،‬کاربرد اين تسهیلت درمیان همة برنامه‌ها يکسان است‪.‬‬

‫ساير ويژگي ها‪ ،‬مانند فايلها و لوله‌های شل‪ ،‬حقیقتا ً توسط کرنل تهیه مي‌شوند‪ ،‬اما شل برای ايجاد آنها دارای نمو طبیعي مي‌باشد‪ .‬آنها‬ ‫بیشتر از چیزی که مناسب است‪ ،‬توانايي های سیستم را افزايش مي دهند‪.‬‬

‫قسمت اعظم قدرت و سهولت شل‪ ،‬از کرنل يونیکسي مي باشد که در زير آن قرار دارد‪ :‬برای مثال‪ ،‬اگرچه شل‪ ،‬لوله‌ها را نصب مي‌کند‬


‫محیط برنامه سازی لینوکس‬

‫‪91/322‬‬

‫اماکرنل حقیقتا ً داده‌ها را به درون آنها وارد مي‌کند‪ .‬روشي که بر طبق آن‪ ،‬سیستم فايلهای قابل اجرا را بوجود مي آورد‪ ،‬امکان نوشتن‬ ‫فايلهای شل را بوجود مي‌آورد و در نتیجه آنها دقیقاً شبیه برنامه‌های کامپايل شده اجرا مي‌شوند‪ .‬کاربر نبايد مطلع باشد که آنها فايلهای‬

‫فرمان هستند ـ به آنها با يك فرمان خاص مانن د ‪ RUN‬استفاده نمي‌شود‪ .‬همچنین شل خودش يك برنامه است و بخشي از کرنل‬

‫نمي‌باشد‪ ،‬در نتیجه مي تواند تنظیم شود‪ ،‬گسترش يابد و شبیه هر برنامة ديگری استفاده شود‪ .‬اين عقیده برای سیستم يونیکس بي‌نظیر‬

‫نمي باشد‪ ،‬اما بهتر از هرجای ديگری استفاده شده است‪.‬‬

‫در فصل ‪ ۵‬ما به موضوع برنامه نويسي شل باز مي‌گرديم‪ ،‬اما شما بايد به خاطر داشته باشید که هرکاری که شما با شل انجام مي‌دهید ‪:‬‬

‫شما آن را برنامه‌نويسي مي‌کنید ‪ -‬به همین دلیل است که به خوبي کار مي‌کند ‪.‬‬

‫تاريخچه و نكات كتاب شناسي‬ ‫شل‪ ،‬از همان زمان‌های اولیه‪ ،‬قابل برنامه نويسي بوده است‪ .‬در اصل‪ ،‬فرمانهای مجزايي برای ‪ if ، goto‬و ‪ lables‬وجود داشتند و فرمان‬

‫‪ goto‬که از طريق مرور فايل ورودی عمل مي‌کند‪ ،‬از ابتدا به دنبال ‪ lable‬صحیح مي‌باشد‪( .‬چون اين امکان وجود ندارد که يك لوله‬ ‫مجدد ًا خوانده شود‪ ،‬اين امکان وجود ندارد که درون يك فايل شلي را لوله گذاری کنیم که دارای جريان کنترل بوده است)‪.‬‬

‫هفتمین ويرايش شل‪ ،‬در ابتدا توسط استیوبورن با کمك و عقايد جون ماشری همچنانکه در فصل ‪ ۵‬خواهیم ديد‪ .‬به علوه‪ ،‬ورودی و‬ ‫خروجي توجیه مي‌شوند‪ :‬اين امکان وجود دارد که ‪ I/O‬را در داخل و خارج ازبرنامه‌های شل بدون محدوديت‪ ،‬تغییر جهت دهیم‪.‬‬

‫تجزية فراکاراکترهای اسم فايل نیز برای اين شل دروني مي‌باشد; تجزيه يك برنامة مجزا درنسخه‌های اولیه بوده است که بايد بر روی‬ ‫ماشینهای خیلي کوچك قرار گیرد‪.‬‬

‫يك شل مهم ديگر‪ ،‬که ممکن است شما در ‪ csh‬اجرا کنید (حتي ممکن است شما آن را ترجیحا ً استفاده کنید) شل ‪ C‬مي‌باشد که‬ ‫دربرکلي توسط بیل جوی با ايجاد ششمین ويرايش شل‪ ،‬توسعه يافت‪ .‬شل ‪ ، C‬بیشتر از شل بورن در جهت واکنش کمکي متقابل‬

‫استفاده شده است ـ بويژه اين شل‪ ،‬يك مکانیسم تاريخي را فراهم مي‌کند امکان تکرار خلصه نويسي فرمانهايي را مي‌دهد که قبلً‬

‫صادر شده‌اندـ (شايد با اندکي ويرايش)‪ .‬نمو‪ ،‬نیز ت ا حدودی متفاوت مي‌باشد‪ .‬اما چون براساس ش ل قبلي مي‌باشد‪ ،‬ازسهولت‬ ‫برنامه‌نويسي کمتری برخوردار است؛ و نمو‪ ،‬بیشتر يك مفسر فرمان محاوره‌ای مي‌باشد تا يك زبا برنامه‌نويسي‪ .‬بويژه‪ ،‬اين امکان وجود‬

‫ندارد که در داخل يا خارج از ساختهای جريان کنترل را لوله‌گذاری کنیم‪.‬‬

‫‪ Pick‬توسط تام داف اختراع شد و ‪ bunddle‬به طور مستقل توسط آلن هیرت و جیمز گاسلینگ اختراع شد‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪92/322‬‬


‫محیط برنامه سازی لینوکس‬

‫‪93/322‬‬

‫فصل ‪ : 4‬فیلترها‬ ‫يك خانواده بزرگ از برنامه‌های يونیکس وجود دارد که ورودی را مي‌خوانند‪ ،‬يك تبديل ساده را بر روی آن انجام مي‌دهند و خروجي‬

‫را مي‌نويسند‪ .‬مثالهايي از اين قبیل شامل ‪ grep‬و ‪ tail‬مي‌باشند که بخشي از ورودی را انتخاب مي‌کنند‪ sort ،‬که آن را ترتیب‌بندی‬ ‫مي‌کند‪ Wc ،‬که آن را مي‌شمرد و مواردی از اين قبیل‪ .‬چنین برنامه‌هايي ‪ ،‬فیلتر نامیده مي‌شوند‪.‬‬

‫اين فصل‪ ،‬فیلترهايي را که غالباً مورد استفاده قرار مي‌گیرند مورد بحث و بررسي قرار مي‌دهد‪ .‬ما با ‪ grep‬آغاز مي‌کنیم و بر طرحهايي‬

‫متمرکز مي‌شويم که پیچیده‌تر از طرحهای شرح داده شده در فصل ‪ ۱‬مي‌باشند‪ .‬ما همچنین به دو عضو ديگر از خانواده ‪ grep‬يعني‬ ‫‪ egrep‬و ‪ fgrep‬مي‌پردازيم‪.‬‬

‫بخش بعد به طور خلصه تعدادی ديگر از فیلترهای مفید را توصیف مي‌کند که شامل ‪ tr‬برای حرف‌نگاری کاراکتر‪ dd ،‬برای پرداختن‬ ‫به داده‌هايي از ساير سیستم‌ها و ‪ unig‬برای آشکارسازی سطرهای تکرار شده متن مي‌باشند‪ Sort .‬نیز به طور مفصل‌تر از فصل ‪ ۱‬ارائه‬ ‫مي‌شود‪.‬‬

‫مابقي فصل ‪ ،‬به دو هدف کلي مبدل‌های داده‌ها يا فیلترهای برنامه‌پذير‪ ،‬اختصاص دارد‪ .‬آنها به اين دلیل برنامه‌پذير نامیده مي‌شوند که‬

‫تبديل ويژه به عنوان يك برنامه در يك زبان ساده برنامه‌نويسي‪ ،‬بیان مي‌شود‪ .‬برنامه‌های متفاوت مي‌توانند تبديلهای بسیار متفاوت را‬ ‫بوجود ‌آورند‪.‬‬

‫برنامه‌ها عبارت از ‪ ، sed‬که برای ويراستار جريان مي‌باشد و ‪ a w k‬که پس از نويسندگانش ‪ ،‬نامگذاری مي‌شود مي‌باشند‪ .‬هر دو‬ ‫برنامه از يك تعمیم از ‪ grep‬مشتق مي‌شوند ‪:‬‬

‫… ‪$ program pattern – action filenames‬‬ ‫فايلها را به طور متوالي پويش مي‌کند و به دنبال سطرهايي مي‌باشد که يك طرح را تطبیق مي‌دهند؛ زماني که کشف مي‌شود عملکرد‬ ‫مربوطه انجام مي‌شود‪ .‬برای ‪ ،grep‬طرح يك بیان منظم مانند ‪ ed‬مي‌باشد و عملکرد پیش فرض‪ ،‬پرينت کردن هر سطری مي‌باشد که‬

‫طرح را تطبیق مي‌دهد‪.‬‬

‫‪ sed‬و ‪ ، awk‬هم طرحها و هم عملکردها را تعمیم مي‌کنند‪ ، Sed .‬يك مشتق از ‪ ed‬مي‌باشد و يك برنامه از فرمانهای ويراستار و‬

‫داده‌های جرياني مي‌گیرد که از طريق فايلها از آنها عبور مي‌کنند و فرمانهای برنامه را روی هر سطر انجام مي‌دهند‪ awk .‬برای‬ ‫جايگزيني متن به سهولت ‪ sed‬نمي‌باشد‪ ،‬اما شامل حساب‪ ،‬متغیرها‪ ،‬تابعهای توکار و يك زبان برنامه‌نويسي مي‌باشد که اندکي شبیه به‬

‫زبان ‪ c‬است‪ .‬اين فصل دارای يك داستان کامل در مورد هر برنامه نمي‌باشد و جلد ‪ ۲۰‬از کتاب راهنمای برنامه‌نويس يونیکس دارای‬ ‫برنامه‌های آموزشي درخصوص هر دو برنامه مي‌باشد‪.‬‬

‫‪grep  ۴.۱‬‬ ‫ما در فصل ‪ ۱‬به طور خلصه در مورد ‪ grep‬ذکر کرديم و از آن موقع از آن در مثالهايي استفاده کرده‌ايم‪.‬‬

‫…‪$ grep pattern filp-nomes‬‬ ‫به جستجوی فايلهای نامگذاری شده يا ورودی استاندارد مي‌پردازد و هر سطری را پرينت مي‌کند که شامل يك مورد از طرح باشد‪.‬‬ ‫‪ grep‬برای پیدا کردن رخدادهای متغیرها در برنامه‌ها و يا کلمات در اسناد و يا برای پیدا کردن قسمتهايي از خروجي يك برنامه‪ ،‬ارزشي‬

‫ندارد ‪:‬‬


‫محیط برنامه سازی لینوکس‬

‫‪94/322‬‬

‫متغیر را در منبع ‪ c‬قرار دهید‬ ‫‪grep from $ maIl‬‬

‫‪$‬‬

‫‪grep from $ maIl | grep – v mary‬‬

‫[‪$ grep – n variable * . ]ch‬‬ ‫عنوانهای پیام را در صندوق پستي پرينت کنید‬ ‫نبودند ‪ mary‬عنوانها از‬

‫‪$‬‬

‫‪$ grep – y mary $ Home/lib/phone-book‬‬ ‫‪who | grep mary‬‬

‫‪$‬‬

‫‪$ Is | grep – v temp‬‬

‫شماره تلفن مری را پیدا کنید‬

‫ببینید که آيا مری با سیستم ارتباط دارد‬

‫نمي‌باشند ‪ temp‬اسامي فايلهايي که شامل‬

‫انتخاب –‪ ، n‬تعداد سطرها را پرينت مي‌کند‪ ،‬انتخاب – ‪ ، v‬حس امتحان را تبديل مي‌کند و – ‪ y‬حروف جعبه پائیني را در حروف‬

‫تطبیق طرح همان جعبه در فايل مي‌سازد (جعبه باليي نیز فقط جعبه باليي را تطبیق مي‌دهد)‪.‬‬

‫در همه مثالهايي که تاکنون مشاهده کرده‌ايم‪ grep ،‬به دنبال رشته‌های معمولي حروف و اعداد بوده است‪ .‬اما ‪ grep‬مي‌تواند حقیقتا ً در‬

‫جستجوی طرحهای پیچیده‌تر باشد ‪ ، grep :‬بیان‌ها را در يك زبان ساده برای توصیف رشته‌ها تفسیر مي‌کند‪.‬‬

‫از نظر تکنیکي ‪ ،‬طرحها اندکي يك شکل محدود شده از مشخص کننده‌های رشته مي‌باشند و عبارت منظم نامیده مي‌شوند‪Grep .‬‬

‫همان عبارت منظم مانند ‪ ed‬را تفسیر مي‌کند؛ در حقیقت ‪ grep‬در ابتدا (در يك بعدازظهر) از طريق عمل مستقیم بر روی ‪ ed‬بوجود‬ ‫آمد‪.‬‬

‫عبارتهای منظم با دادن معني ويژه به کاراکترهای خاص‪ ،‬مشخص مي‌شوند‪ ،‬درست شبیه * و غیره که توسط شل استفاده مي‌شوند‪ .‬فرا‬

‫کاراکترهای بیشتری وجود دارند و متاسفانه دارای تفاوتهايي در معاني خود مي‌باشند‪ .‬جدول ‪ ۴.۱‬همه فراکاراکرهای عبارت منظم را‬

‫نشان مي‌دهد اما به طور خلصه در اينجا به مرور آنها مي‌پردازيم‪.‬‬

‫فرا کارکترهای ^ و ‪ $‬طرح را برای شروع (^) يا پايان (‪ )$‬سطر تثبیت مي‌کنند‪ .‬برای مثال ‪،‬‬ ‫فايلهايي را که شامل ‪ From‬مي‌باشند در صندوق پستي شما قرار مي‌دهد اما‬

‫‪grep From $ MAIL‬‬

‫‪$‬‬

‫‪$ grep ′^ From′ $ MAIL‬‬ ‫سطرهايي را پرينت مي‌کند که با ‪ Form‬آغاز مي‌شوند‪ ،‬که به احتمال قوی سطرهايي با عنوان پیغام مي‌باشند‪ .‬فراکاراکترهای عبارت‬

‫منظم‪ ،‬با فراکاراکترهای شل هم‌پوشاني مي‌کنند‪ ،‬بنابراين همیشه يك عقیده خوب برای ضمیمه کردن طرحهای ‪ grep‬در نقل‌های منفرد‬ ‫وجود دارد‪.‬‬

‫‪ ،grep‬طبقه‌هايي از کاراکترها را حمايت مي‌کند که بسیار شبیه به کارکترهای موجود در شل مي‌باشند‪ ،‬بنابراين [‪ ،]a-z‬هر گونه حرف‬

‫در جعبه پائیني را تطبیق مي‌کند‪ .‬اما تفاوتهايي وجود دارند ‪ :‬اگر يك طبقه از کاراکتر ‪ grep‬با يك سیرکومفلکس ^ ‪ ،‬آغاز شود طرح هر‬

‫کاراکتری را تطبیق مي‌کند‪ ،‬به جز کاراکترهايي را که در طبقه وجود دارند ‪.‬‬

‫بنابراين‪ ]9– 0 ^ [ ،‬هر گونه کاراکتر غیر رقمي را تطبیق مي‌کند‪ .‬همچنین در شل يك پس کج خط از ‪ l‬و ــ ‪ ،‬در يك طبقه از کاراکتر‬

‫محافظت مي‌کند‪ ،‬اما ‪ grep‬و ‪ ed‬مستلزم اين هستند که کاراکترها درجايي آشکار شوند که معني آنها مبهم نباشد ‪ .‬برای مثال‪]-[ ]sil[ ،‬‬

‫[ ] ‪ ،‬يك کروشه مربع بسته يا باز و يا يك علمت منها را تطبیق مي‌کند‪.‬‬

‫يك دوره « ‪ » .‬معادل ؟ شل مي‌باشد ‪ :‬هر گونه کاراکتری را تطبیق مي‌کند‪( .‬دوره احتمال کاراکتر با متفاوت‌ترين معني برای برنامه‌های‬


‫محیط برنامه سازی لینوکس‬

‫‪95/322‬‬

‫متفاوت يونیکس مي‌باشد) در اينجا دو مثال وجود دارد ‪:‬‬

‫فهرست اسامي راهنماي فرعي‬

‫‪$‬‬

‫‪Is - 1 | grep ′^d′‬‬

‫فهرست فايلهايي كه مي‌توانند خوانده و نوشته شوند ‪$‬‬

‫‪Is - 1 | grep ′^ …… rw′‬‬

‫« ^ » و هفت د وره‪ ،‬هر هفت کاراکتر را در آغاز سطر تطبیق مي‌دهند[‪ ،‬زماني که از خروجي ‪ Is-1‬به معنای هر رشته مجاز‪ ،‬استفاده‬ ‫مي‌کنند‪.‬‬

‫عملگر ستبار * برای کاراکتر يا فراکاراکتر قبلي (شامل يك طبقه از کاراکتر) در عبارت بکار مي‌رود و آنها جمعاً تعداد تطبیق‌های موفق‬ ‫کاراکتر يا فراکاراکتر را تطبیق مي‌کنند ‪ .‬برای مثال‪ *x ،‬يك توالي از ‪ x’s‬را تا جايي که امکان دارد تطبیق مي‌کند‪،‬‬

‫[ ‪ ، * ]a – ZA – Z‬يك رشته الفبايي را تطبیق مي‌کند‪ * ،‬هر چیزی را تا سطر جديد تطبیق مي‌کند و * ‪ ، .x‬هر چیزی را تا زمان داشتن‬

‫آخرين ‪ x‬بر روی سطر تطبیق مي‌کند‪.‬‬

‫دو چیز مهم قابل توجه در مورد ستبارها وجود دارند‪ .‬روی اينکه‪ ،‬ستبار فقط برای يك کاراکتر بکار مي‌رود‪ ،‬بنابراين ‪ * xy‬يك ‪ x‬را که‬

‫با ‪ y’s‬دنبال مي‌شود تطبیق مي‌کند نه يك توالي مانند ‪ . xy xy xy‬دوم اينکه‪ ،‬هر عددی شامل صفر مي‌باشد‪ ،‬بنابراين اگر شما بخواهید‬

‫که حداقل يك کاراکتر را تطبیق کنید‪ ،‬شما بايد آن را دو نسخه‌ای کنید ‪ .‬برای مثال‪ ،‬برای تطبیق يك رشته از حروف‪ ،‬عبارت صحیح [‪a-‬‬

‫‪ ]ZA-Z[ * ]a – ZA – Z‬مي‌باشد [ يك حرف يا چند حرفي که با ‪ Z‬دنبال مي‌شوند]‪.‬‬ ‫اسم فايل شل * که کاراکتر را تطبیق مي‌کند‪ ،‬شبیه به عبارت منظم *‪ .‬مي‌باشد‪.‬‬

‫هیچ گونه عبارت منظم ‪ ،grep‬يك سطر جديد را تطبیق نمي‌کند؛ عبارتها برای هر سطر به طور جداگانه بکار مي‌روند‪.‬‬

‫با عبارت منظم‪ grep ،‬يك زبان برنامه‌نويسي ساده مي‌باشد‪ .‬برای مثال‪ ،‬به خاطر بیاوريد که دومین میدان فايل کلمه رمز‪ ،‬رمزی کردن‬

‫کلمه رمز مي‌باشد‪ .‬اين فرمان بدون کلمات رمز برای کاربرها به جستجو مي‌پردازد‪:‬‬

‫‪$ grep ′^ ] ^ :[ * : : ′ / etc / passwd‬‬ ‫اين طرح به اين صورت است ‪ :‬آغاز سطر‪ ،‬هر عدد بدون دو نقطه‪ ،‬دو نقطه دوبل ‪ ، grep‬در حقیقت‪ ،‬قديمي‌ترين خانواده از برنامه‌ها‬ ‫مي‌باشد‪ ،‬ساير اعضاء آنـ ‪ Fgrep‬وـ ‪ egrep‬نامیده مي‌شوند‪ .‬رفتار اصلي آنها شبیه به هم است‪ ،‬اماـ ‪ fgrep‬به جستجوی بسیاری از‬

‫رشته‌های حرفي به طور همزمان مي‌پردازد‪ ،‬در حالیکه ‪ egrep‬عبارتهای منظم درست را تفسیر مي‌کند ـ همانند ‪ ، grep‬اما با يك عملگر‬

‫‪ or‬و پرانتزها برای گروه بندی کردن عبارتهايي که در زير شرح داده مي‌شوند‪.‬‬

‫هم ‪ fgrep‬و هم ‪ ، egrep‬هر دو برای مشخص کردن يك فايل که از آن طرح را بخوانند انتخاب –‪ f‬را مي‌پذيرند‪ .‬در فايل‪ ،‬سطرهای‬ ‫جديد‪ ،‬طرحهايي را که بايد مورد جستجو قرار بگیرند به طور موازی از هم جدا مي‌کنند‪ .‬اگر کلماتي باشند که شما بر حسب عادت به‬

‫طور تلفظ مي‌کنید‪ ،‬شما مي‌توانید اسناد خود را برای چنین رخدادی‪ ،‬با حفظ آنها در يك فايل‪ ،‬درهر سطر و با استفاد از ‪ fgrep‬کنترل‬ ‫کنید ‪:‬‬

‫‪$ fgrep - f common – errors document‬‬ ‫عبارتهاي منظم تفسير شده توسط ‪( egrep‬كه در جدول ‪ ۴.۱‬نيز فهرست وار وجود دارند)‬ ‫شبيه عبارات موجود ‪ ، grep‬با دو مورد اضافه مي‌باشند‪ .‬پرانتزها مي‌توانند براي گروه‌بندي‬ ‫كردن استفاده شوند‪ ،‬بنابراين (‪ *) x y‬هر رشته خالي را تطبيق مي‌كند‪xy ، xy xy ، xy ،‬‬ ‫‪ xy xy‬و به همين ترتيب‪ .‬نوار عمودي | يك عملگر" ‪" or‬مي‌باشد; ‪ - today | tommorow‬امروز يا‬ ‫فردا را تطبيق مي‌كند همانند ‪ . )to )day | morrow‬در آخر اينكه دو عملگر ستبار ديگر در ‪egrep‬‬


‫محیط برنامه سازی لینوکس‬

‫‪96/322‬‬

‫وجود دارند‪ + .‬و ؟ ‪ .‬طرح ‪ x +‬يك يا چند ‪ x’s‬را تطبيق مي‌كند و ‪ ? x‬صفر يا يك ‪ x‬را تطبيق‬ ‫مي‌كند و نه بيشتر‪.‬‬ ‫‪، Grep‬ت تدرت تبازيت تكلماتت تعاليت تاستت توت تشاملت تجستجويت تفرهنگت تلغتت تبرايت تكلماتت تبا‬ ‫ويژگيهاي خاص مي‌باشد‪ .‬فرهنگ لغت ما دومين و بستر بين المللي مي‌باشد و به عنوان‬ ‫فهرستي از لغات‪ ،‬در هر سطر و بدون تعريف ترتيب بندي مي‌شود‪ .‬سيستم شما ممكن‬ ‫است داراي ‪ usr/dict/words /‬باشد‪ ،‬يك فرهنگ لغت كوچكتر كه به كنترل تلفظ مي‌پردازد‪:‬‬ ‫براي كنترل فرمت به آن نگاه كنيد‪ .‬دراينجا يك طرح براي پيدا كردن لغاتي وجوددارد كه حاوی‬ ‫‪ ۵‬و اول در ترتيب الفبايي مي‌باشند ‪:‬‬ ‫‪$ cat alphvowels‬‬ ‫‪^ ]^ aeio[ * a ] ^ a eiou[ * e ] ^ aeiou [ * i ]^ a eiou * o ] ^ a eiou[ * a‬‬ ‫‪] ^ aeio[ * $‬‬ ‫‪$ egrep – f alphrowels‬‬ ‫‪/ usr / dict / web 2 | 3‬‬ ‫‪abstemious‬‬ ‫‪abstemiously‬‬ ‫‪abstentious‬‬ ‫‪acheilous‬‬ ‫‪acheirous‬‬ ‫‪acleistous‬‬ ‫‪affectious‬‬ ‫‪annelidiou‬‬ ‫‪arsenious‬‬ ‫‪arterious‬‬ ‫‪bacterious‬‬ ‫‪caesoious‬‬ ‫‪facetious‬‬ ‫‪facetiously‬‬ ‫‪fracedinous‬‬ ‫‪majectious‬‬ ‫‪$‬‬ ‫طرح‪ ،‬در واولهای الفبايي فايل‪ ،‬ضمیمه نقل قولها نمي‌شود‪ .‬زماني که نقل قولها برای ضمیمه کردن طرحهای ‪ egrep‬استفاده مي‌شوند‪،‬‬ ‫مثل فرمانها را از تفسیر شدن حفظ مي‌کند اما نقل قولها را قطع مي‌کند؛ ‪ egrep‬هرگز آنها را نمي‌بیند‪ .‬چون فايل توسط شل بررسي‬

‫نمي‌شود‪ ،‬نقل قولها در اطراف محتواهای آن استفاده نمي‌شوند‪ .‬ما مي‌توانستیم از ‪ grep‬برای اين مثال استفاده کنیم‪ ،‬اما به خاطر روشي‬

‫که بر طبق آن ‪ egrep‬کار مي‌کند‪ ،‬زماني که به جستجوی طرحهايي بپردازيم که شامل بستار مي‌باشند‪ ،‬اين کار سريعتر انجام مي‌شود‪،‬‬ ‫بويژه زماني که فايلهای بزرگ را پويش مي‌کنیم‪.‬‬

‫به عنوان مثال ديگر‪ ،‬پیدا کردن همه کلمات شش حرفي يا بیشتر مي‌باشد که در ترتیب الفبايي دارای حرف مي‌باشند ‪:‬‬

‫‪$ cat monotonic‬‬ ‫‪^a ? b ? c ? d ? e ? f ? g ? h ? i ? j ? k ? l ? m ? n ? o ? p ? q ? r ? s ? t ? u ? v ? w? x ? y ? z ? $‬‬ ‫‪$ egrep – f monotonic / usr / dict / web 2 | grep ′………′ | 5‬‬ ‫‪abdest‬‬ ‫‪acknow‬‬ ‫‪adipsy‬‬ ‫‪agnosy‬‬ ‫‪almost‬‬ ‫‪befist‬‬ ‫‪behint‬‬ ‫‪beknow‬‬ ‫‪bijoux‬‬ ‫‪biopsy‬‬ ‫‪chinte‬‬ ‫‪debors‬‬ ‫‪dehort‬‬ ‫‪deinos‬‬ ‫‪dimpsy‬‬ ‫‪egilops‬‬ ‫‪ghosty‬‬ ‫‪$‬‬ ‫(‪ ، egilops‬يك نوع بیماری است که به گندم حمله مي‌کند)‪ .‬توجه داشته باشید که استفاده از ‪ grep‬برای فیلتر کردن خروجي ‪grep‬‬ ‫مي‌باشد‪.‬‬

‫چرا سه برنامه ‪ grep‬وجود دارد؟ ‪ ، fgrep‬هيچ فرا كاراكتري را تفسير نمي‌كند اما مي‌تواند‬ ‫به طور موثر به دنبال هزاران لغت به صورت موازي باشد (زماني كه آغاز مي‌شود‪ .‬زمان‬ ‫اجراي تآن تمستقل تاز تتعداد تكلمات تمي‌باشد) وت تبنابراين ت‪،‬ت تدر تابتدا تبراي توظايفي تمانند‬ ‫جستجوهايت تكتابت ت‌شناسيت تاستفادهت تمي‌شود‪ .‬اندازهت تطرحهايت تاصليت ‪،fgrep‬ت تمافوق‬ ‫ظرفيت تآلگوريتم‌هاي تاستفاده تشده تدرت ‪ grep‬وت ‪ egrep‬مي‌باشد‪ .‬تمايز تبينت ‪ grep‬وت ‪ egrep‬به‬


‫محیط برنامه سازی لینوکس‬

‫‪97/322‬‬

‫سختي قابل توجيه است‪ ،grep .‬اندكي زودتر مي‌آيد‪ ،‬عبارات منظم آشنا را از ‪ ed‬مي‌گيرد‬ ‫و بر روي عبارات منظم و يك مجموعه وسيعتري از انتخابها علمت زده است‪ egrep .‬عبارات‬ ‫كلي‌تر را تفسير مي‌كند ( به جز براي علمت زدن) و به طور حائز اهميتي سريعتر اجرا‬ ‫مي‌كند (با سرعتي مستقل از طرح)‪ ،‬امانسخه استاندارد ‪ ،‬زمان بيشتري را براي شروع‬ ‫مي‌گيرد تزماني تكه تعبارت تپيچيده تاست‪ .‬يك تنسخه تجديدتر توجود تدارد تكه تسريعاً تآغاز‬ ‫مي‌شود‪ ،‬بنابراين ‪ egrep‬و ‪ grep‬مي‌توانند اكنون به يك طرح واحد تبديل شوند كه برنامه را تطبيق‬ ‫مي‌كند‪.‬‬ ‫جدول ‪ : ۴.۱‬عبارات منظم ‪ grep‬و ‪egrep‬‬

‫(به ترتیب تقدم)‬

‫هر کاراکتر غیر ويژه ‪ ،c‬خودش را تطبیق مي‌کند‬

‫‪c‬‬

‫هر معني ويژه‌ای از کاراکتر ‪ c‬را خاموش مي‌کند‬

‫\‪c‬‬

‫آغاز سطر‬

‫^‬

‫پايان سطر‬

‫‪$‬‬

‫هر کاراکتر مفرد‬

‫‪0‬‬

‫هر يك از کاراکترها در … قرار دارند ؛ مراتبي مانند ‪ a-z‬مجاز هستند‬

‫[…]‬

‫هر کاراکتری که در … قرار ندارد؛ مراتب مجاز هستند‪.‬‬

‫[ ^ …]‬

‫چیزی که ‪ )\ …( \ n’ th‬تطبیق مي‌شود (فقط (‪grep‬‬

‫‪\n‬‬

‫صفر يا چند رخداد از ‪r‬‬

‫‪*r‬‬

‫يك يا چند رخداد از ‪( r‬فقط (‪egrep‬‬

‫‪+r‬‬

‫صفر يا يك رخداد از ‪( r‬فقط (‪egrep‬‬

‫‪?r‬‬

‫‪ r1‬با ‪ r2‬دنبال مي‌شود‬ ‫‪ r1‬يا ‪( r2‬فقط (‪egrep‬‬ ‫عبارت منظم و دارای علمت ‪( r‬فقط ‪ )grep‬؛ مي‌تواند تودر تو ساخته شود‬ ‫عبارت منظم ‪( r‬فقط ‪ )egrep‬؛ مي‌توند تو در تو ساخته شود‬

‫‪r1r2‬‬ ‫‪r1 | r2‬‬

‫\ (‪)\r‬‬ ‫(‪) r‬‬

‫هیچ عبارت منظمي يك سطر جديد را تطبیق نمي‌کند‪.‬‬

‫تمرين ‪ .۱-۴‬عبارات منظم دارای علمت ( (\ (‪ ) | )and‬را در ضمیمه ‪ ۱‬يا (‪ ed )۱‬پیدا کنید و از ‪ grep‬برای جستجوی جناسهای قلبي‬ ‫استفاده کنید ـ کلمات به صورت عقب رو و جلورو تلفظ مي‌شوند‪ .‬توجه ‪ :‬يك طرح متفاوت برای هر طول کلمه بنويسید‪.‬‬

‫تمرين ‪ . ۴.۲‬ساختار ‪ grep‬برای خواندن يك سطر مفرد مي‌باشد‪ ،‬آن را برای تطبیق کنترل کنید‪ ،‬سپس آن را حلقه ‌سازی کنید‪grep .‬‬

‫چگونه تحت تأثیر قرار مي‌گیرد اگر عبارات منظم بتوانند سطرهای جديد را تطبیق دهند؟‬ ‫‪ ۴.۲‬ساير فیلترها‬

‫هدف اين بخش‪ ،‬آگاه کردن شما درخصوص وجود و توانايي‌های يك مجموعه غني از فیلترهای کوچکي مي‌باشد که توسط سیستم‬


‫محیط برنامه سازی لینوکس‬

‫‪98/322‬‬

‫تهیه مي‌شوند و ارائه مثالهايي درخصوص استفاده از آنها مي‌باشد‪ .‬اين فهرست به هیچ وجه کامل نمي‌باشد ـ تعداد زياد ديگری نیز‬

‫هستند که بخشي از هفتمین ويرايش بودند و هر نصب ‪ ،‬بخشي از خودش را بوجود مي‌آورد‪ .‬همه فیلترهای استاندارد در بخش اول‬ ‫کتاب راهنما توصیف مي‌شوند‪.‬‬

‫ما با ‪ sort‬آغاز مي‌کنیم که احتمال ً مفیدترين آنها مي باشد‪ .‬اصول اولیه ‪ sort‬در فصل اول‪ ،‬ارائه شدند ‪ ، sort :‬ورودی خود را با يك‬

‫سطر در ترتیب ‪ ASCII‬ترتیب‌بندی مي‌کند‪ .‬اگر چه اين يك مورد بديهي است که با پیش فرض انجام مي‌شود‪ ،‬اما راههای بسیار‬

‫ديگری نیز وجود دارند که فرد مي‌خواهد از آن طريق داده‌ها را ترتیب‌بندی کند و ‪ sort‬درصدد فراهم کردن اين راهها از طريق ارائه‬

‫انتخابهای متفاوت برای آنها مي‌باشد‪ .‬برای مثال ‪ ،‬انتخاب – ‪ ، f‬باعث مي‌شود که جعبه باليي و پائیني تا شوند و در نتیجه تفاوتهای‬ ‫جعبه حذف مي‌شوند‪ .‬انتخاب –‪( d‬به ترتیب فرهنگ لغت) همه کاراکترها به جز حروف‪ ،‬ارقام و فاصله در مقايسه‌ها را ناديده مي‌گیرد‪.‬‬

‫اگر چه مقايسه‌های الفبايي بسیار عمومي هستند‪ ،‬اما گاهي اوقات يك مقايسه عددی لزم است‪ .‬انتخاب – ‪ n‬توسط ارزش عددی‬

‫ترتیب بندی مي‌کند و انتخاب –‪ r‬حس هر گونه مقايسه‌ای را تغییر مي‌دهد‪ .‬بنابراين ‪،‬‬

‫اسامي فايلها را به ترتيب الفبايي ترتيب بندي مي‌كند‬ ‫با كوچكترين فايلها مرتب مي‌كند‬ ‫با بزرگترين فايلها مرتب مي‌كند‬

‫‪s | sort – f / $‬‬ ‫‪$‬‬

‫‪$‬‬

‫‪s | sort – n /‬‬

‫‪s - s | sort – nr /‬‬

‫‪ ، sort‬در حالت عادی بر روی يك سطر کامل ترتیب‌بندی مي‌کند‪ ،‬اما مي‌توان گفت که توجه خود را فقط به زمینه‌های خاص متمرکز‬ ‫مي‌کند‪ .‬نماد ‪ +m‬به معنای اين است که مقايسه از اولین زمینه‌های ‪ m‬جست مي‌زند؛ ‪ +o‬آغاز سطر است‪ .‬بنابراين ‪ ،‬برای مثال‪،‬‬

‫با شمارش بايت ‪ ،‬از بزرگترين مرتب مي‌شود‬ ‫با زمان ‪ ، login‬از قديمي‌ترين مرتب مي‌شود‬

‫‪$‬‬

‫‪s - 1 | sort + 3 nr /‬‬ ‫‪who | sort + 4n $‬‬

‫ساير انتخابهای مفید ‪ sort‬شامل ‪ - o‬مي‌باشند که يك اسم فايل را برای خروجي مشخص مي‌کند (اين انتخاب مي‌تواند يکي از فايلهای‬ ‫ورودی باشد) و ‪ - u‬که همه‪ ،‬به جز يکي از گروههای سطرها را که در زمینه‌های ‪ sort‬مشابه هستند‪ ،‬حذف مي‌کند‪.‬‬

‫کلیدهای متعدد ‪ sort‬مي‌توانند استفاده شوند‪ ،‬همچنانکه با اين مثال رمزی از ‪ sort‬صفحه کتاب راهنما شرح داده مي‌شود ‪:‬‬

‫‪$ sort + of + o - u filenames‬‬ ‫‪ ، + of‬سطر را مرتب مي‌کند‪ ،‬جعبه باليي و پائیني را با هم تا مي‌کند‪ ،‬اما سطرهايي که مشابه هستند‪ ،‬نمي‌توانند مجاور هم باشند ‪.‬‬

‫بنابراين ‪ + o‬دومین کلید است که سطرهای يکسان از اولین ‪ sort‬را در ترتیب عادی ‪ ASCII‬مرتب مي‌کند‪ .‬در آخر ‪ -u ،‬نسخه‌های‬

‫مجاور را از هم جدا مي‌کند‪ .‬بنابراين با توجه به فهرست کلمات و هر سطر‪ ،‬فرمان‪ ،‬لغات بي‌نظیری را پرينت مي‌کند‪ .‬شاخص برای اين‬

‫کتاب با يك فرمان ‪ sort‬مشابه تهیه شد‪ ،‬که حتي بیشتر‪ ،‬از توانايي‌های ‪ sort‬استفاده مي‌کند‪ .‬به ‪ sortcu‬مراجعه کنید‪.‬‬

‫فرمان ‪ ، uniq‬الهام برای نشانه ـ ‪ -u‬از ‪ sort‬مي‌باشد ‪ :‬اين فرمان ‪ ،‬همه‪ ،‬به جز يك گروه از سطرهای نسخه‌ای مجاور را از هم جدا‬

‫مي‌کند‪ .‬داشتن يك برنامه مجزا برای اين عملکرد منجر به انجام وظايف بدون ارتباط با ترتیب‌بندی مي‌شود‪ .‬برای مثال‪،‬ـ ‪، uniq‬‬

‫سطرهای فاصله متعدد را حذف مي‌کند‪ ،‬حال چه ورودی آن مرتب شود و چه مرتب نشود‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪99/322‬‬

‫انتخابها به روشهای خاصي برای پردازش نسخه‌ها استفاده مي‌کنند ‪ uniq - d :‬فقط سطرهايي را پرينت مي‌کند که دو نسخه‌ای مي‌شوند‬ ‫؛ ‪ uniq-u‬فقط سطرهايي را پرينت مي‌کند که بي‌نظیر مي‌باشند‪( .‬يعني دو نسخه‌ای نمي‌باشند) و ‪ uniq- c‬تعداد رخدادهای هر سطر را‬

‫مي‌شمارد‪.‬‬

‫ما به يك مثال به طور خلصه مراجعه خواهیم کرد‪.‬‬

‫فرمان ‪ comm‬يك برنامه مقايسه فايل مي‌باشد‪ .‬با توجه به دو فايل ورودي مرتب شده ‪ f1‬و ‪f‬‬ ‫‪ 2 ، comm‬سه ستون از خروجي را پرينت مي‌كند ‪:‬‬ ‫ي‌دهند‪ ،‬سطرهايي كه فقط در ‪ f2‬رخ مي‌دهند و سطرهايي‬ ‫سطرهايي كه فقط در ‪ f1‬رخ م ‌‬ ‫كه در هر دو فايل رخ مي‌دهند‪ .‬هر كدام از اين ستونها مي‌توانند توسط يك انتخاب حذف‬ ‫شوند ‪:‬‬ ‫‪$ comm – 12 f1 f2‬‬ ‫فقط سطرهايي را پرينت مي‌کند که در هر دو فايل قرار دارند و‬

‫‪$ comm – 23 f1f2‬‬ ‫سطرهايي را پرينت مي‌کند که در اولین فايل وجود دارند‪ ،‬اما در دومین فايل نمي‌باشند‪ .‬چنین چیزی برای مقايسه فهرست ها را برای‬ ‫مقايسه يك فهرست کلمه با يك فرهنگ لغت‪ ،‬مفید است‪.‬‬

‫فرمان ‪ ،tr‬کاراکترها را در ورودی خودش ترجمه مي‌کند‪ .‬تاکنون عمومي‌ترين استفاده از ‪ ،tr‬تبديل مورد مي‌باشد ‪:‬‬

‫از مورد پائین به مورد باليي مي‌نگارد‬

‫از مورد باليي به مورد پائیني مي‌نگارد‬

‫‪tr a- Z A - Z $‬‬ ‫‪tr AZ a – Z $‬‬

‫فرمانـ ‪ dd‬تا حدودی متفاوت از ساير فرمانهايي مي‌باشد که ما ديده‌ايم‪ .‬اين فرمان در ابتدا فقط قصد بررسي داده‌های نوار را از‬

‫سیستم‌های ديگر دارد ـ نام آن يك باقیمانده از زبان کنترل کار ‪ os /360‬مي‌باشد‪ ،dd .‬تبديل مورد را انجام مي‌دهد (با يك نحو خیلي‬ ‫متفاوت از ‪ )tr‬؛ ‪ ،dd‬از ‪ ASCII‬به ‪ EBCDIC‬و بالعکس تبديل مي‌کند؛ و داده‌ها را در ثبتیاتي با اندازه ثابت‪ ،‬با سبط‌ دهي فاصله‌ای که‬

‫سیستم‌های غیر يونیکس را توصیف مي‌کنند‪ ،‬مي‌خواند يا مي‌نويسد‪ .‬در عمل‪ dd ،‬اغلب برای پرداختن به داده‌های خام و فرمت نشده‬ ‫استفاده مي‌شود‪ ،‬با هر منبعي که باشند؛ ‪ ، dd‬يك مجموعه از امکانات را برای پرداختن به داده‌های دوگانه‪ ،‬آشکار مي‌سازد‪.‬‬

‫برای شرح چیزی که مي‌توان با ترکیب فیلترها انجام داد‪ ،‬خط لوله‌‌ای زير را در نظر بگیريد‪ ،‬که غالبا ‪ 10‬کلمه را در ورودی خود پرينت‬

‫مي‌کند ‪:‬‬

‫| * ‪$‬‬

‫اجراهای غير حرفی را در سطر جدید متراکم کنيد‬

‫‪cat‬‬

‫|'‪tr – sc A-za-z '\ 012‬‬ ‫| ‪sort‬‬ ‫| ‪uniq – c‬‬ ‫| ‪sort – n‬‬ ‫| ‪tail‬‬

‫‪5‬‬


‫محیط برنامه سازی لینوکس‬

‫‪100/322‬‬

‫‪ ، cat‬فايلها را جمع‌آوری مي‌کند‪ ،‬چون ‪ ، tr‬فقط ورودی استاندارد خود را مي‌خواند‪ ،‬فرمان ‪ ، tr‬از کتاب راهنما مي‌باشد ‪ :‬اين فرمان‬

‫موارد غیر حرفي مجاور را در سطرهای جديد متراکم مي‌کند‪ ،‬بنابراين‪ ،‬ورودی را به يك کلمه درهر سطر تبديل مي‌کند ‪ .‬کلمات در‬

‫نتیجه مرتب مي‌شوند و ‪ uniq-c‬هر گروه از کلمات مشابه را در يك سطری متراکم مي‌کند که دارای پیشوند تعداد مي‌باشد و برای ‪sort‬‬

‫‪ ، – n‬به زمینه ترتیب بندی تبديل مي‌شود‪( .‬اين ترکیب از دو ترتیب‌بندی در اطراف يك ‪ uniq‬که اغلب رخ مي‌دهد‪ ،‬يك شیوه نامیده‬ ‫مي‌شود)‪ .‬نتیجه‪ ،‬کلمات بي‌نظیر در سند مي‌شود که درتکرار در حال افزايش مرتب مي‌شوند‪tail، ۱۰ .‬مورد از عمومي‌ترين کلمات را‬

‫انتخاب مي‌کند (انتهای فهرست مرتب شده) و ‪ ۵‬آنها را در ‪ ۵‬ستون پرينت مي‌کند‪.‬‬

‫در ضمن‪ ،‬توجه داشته باشید که اتمام يك سطر با | ‪ ،‬يك روش معتبر برای ادامه آن مي‌باشد‪.‬‬

‫تمرين ‪ .۴.۳‬در اين بخش از ابزار برای نوشتن يك کنترل کننده ساده تلفظ‪ ،‬با استفاده از‬

‫‪ usr/ dict / words /‬استفاده کنید‪ .‬کمبودهای آن چیست و شما چگونه آنها را مورد خطاب قرار مي‌دهید؟‬

‫تمرين ‪ .۴.۴‬يك برنامه شمارش کلمه به زبان برنامه‌نويسي مورد علقه خود بنويسید و اندازه‪ ،‬سرعت و قابلیت حفظ آن را با خط‬ ‫لوله‌ای شمارش کلمه مقايسه کنید‪ .‬چقدر آسان شما مي‌توانید آن را به يك کنترل کننده تلفظ تبديل کنید ؟‬

‫‪ ۴.۳‬ويراستار جريان ‪sed‬‬ ‫اکنون به سراغ ‪ sed‬مي‌رويم‪ .‬چون ‪ sed‬مستقیما ً از ‪ ed‬مشتق مي‌شود‪ ،‬يادگیری آن بايد آسان باشد و ‪ sed‬آگاهي شما را در مورد ‪، ed‬‬

‫تقويت مي‌کند‪ .‬ايده اصلي درخصوص ‪ sed‬ساده است ‪:‬‬

‫… ‪$ sed ′ list of ed commands ′ filenames‬‬ ‫سطرها را از فايلهای ورودی مي‌خواند البته در هر زمان يك سطر ؛ فرمانهايي را از فهرست برای هر سطر بکار مي‌برد و شکل ويرايش‬ ‫شده آن را بر روی خروجي استاندارد مي‌نويسد‪ .‬بنابراين‪ ،‬برای مثال‪ ،‬شما مي‌توانید يونیکس را به يونیکس ( ‪ ) tm‬تبديل کنید‪ .‬در‬ ‫هرجايي که در يك مجموعه از فايلها با فرمان زير رخ مي‌دهد ‪:‬‬

‫‪$ sed ′ s / unix / unix )Tm( / g′ filenames … > output‬‬ ‫چیزی را که در اينجا رخ مي‌دهد به غلط تفسیر نکنید‪ ،Sed .‬محتواهای فايلهای ورودی خود را تغییر نمي‌دهد‪ Sed .‬بر روی خروجي‬

‫استاندارد مي‌نويسد‪ ،‬در نتیجه ‪ ،‬فايلهای اصلي تغییر نمي‌کنند‪ .‬اکنون شما تجربه کافي درخصوص مثل داريد برای اينکه پي ببريد که‬

‫‪$ sed ′ … ′ file > file‬‬ ‫يك ايده خوبي نیست ‪ :‬برای جايگزين کردن محتواهای فايلها‪ ،‬شما بايد از يك فايل موقت يا برنامه‌ای ديگر استفاده کنید‪( .‬ما بعداً در‬ ‫مورد يك برنامه برای آشکار کردن ديده مربوط به روی هم نوشتن يك فايل موجود صحبت خواهیم کرد؛ به روی هم‌نويسي در فصل ‪۵‬‬ ‫مراجعه کنید)‪.‬‬

‫‪ Sed‬هر سطر به صورت اتوماتیك خارج مي‌شود‪ ،‬در نتیجه بهـ ‪ p‬پس از جايگزيني فرمان بال نیازی نیست؛ حقیقتاًـ اگر يكـ ‪p‬‬

‫وجودداشت‪ ،‬هر سطر اصلح شده‪ ،‬دو بار پرينت مي‌شد‪ .‬نقل قولها تقريبا ً همیشه لزم هستند‪ ،‬چونبسیاری از فراکاراکترهای ‪ sed‬برای‬

‫شل دارای معني مي‌باشند‪ .‬برای مثال ‪ ،‬استفاده از ‪ du – a‬را برای ايجاد يك فهرست از اسامي فايلها در نظر بگیريد‪ .‬در حالت عادی‪da ،‬‬ ‫ـ اندازه و اسم فايل را پرينت مي‌کند ‪:‬‬

‫* ‪du – a ch 4 .‬‬

‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪101/322‬‬

‫‪18‬‬ ‫‪ch 4. 1‬‬ ‫‪13‬‬ ‫‪ch 4. 2‬‬ ‫‪14‬‬ ‫‪ch 3. 4‬‬ ‫‪17‬‬ ‫‪ch 4. 4‬‬ ‫‪2‬‬ ‫‪ch 4. 9‬‬ ‫‪$‬‬ ‫شما مي‌توانید از ‪ sed‬برای کنار گذاشتن (حذف) بخش اندازه استفاده کنید‪ ،‬اما فرمان ويرايش نیازمند نقل قولها برای محافظت از يك *‬ ‫و يك جدول از تفسیر شدن توسط شل مي‌باشد ‪:‬‬

‫‪ch 4. * | sed ′ s / . * → // ′‬‬

‫‪$ du – a‬‬ ‫‪ch 4.1‬‬ ‫‪ch 4.2‬‬ ‫‪ch 4.3‬‬ ‫‪ch 4.4‬‬ ‫‪ch 4.9‬‬ ‫‪$‬‬

‫جايگزيني همه كاراكترهاي ( * ‪ )0‬را حذف مي‌كند و شامل راست‌ترين سمت جدول‌بندي‬ ‫مي‌باشد (كه در نمونه به صورت ‪ ‬نشان داده مي‌شود)‪.‬‬ ‫در يك روش مشابه ‪ ،‬شما مي‌توانید اسامي کاربرها و زمانهای ‪ login‬را از خروجي ‪ who‬انتخاب کنید ‪:‬‬

‫‪$ who‬‬ ‫‪1r‬‬ ‫‪tty1‬‬ ‫‪sep 29 07 : 14‬‬ ‫‪ron‬‬ ‫‪tty3‬‬ ‫‪sep 29 10 : 31‬‬ ‫‪you‬‬ ‫‪tty4‬‬ ‫‪sep 29 08 : 36‬‬ ‫‪td‬‬ ‫‪tty5‬‬ ‫‪sep 29 08 : 47‬‬ ‫‪$ who | sed ′s / . * // ′‬‬ ‫‪1r 07 : 14‬‬ ‫‪ron 10 : 31‬‬ ‫‪you 08 : 36‬‬ ‫‪td‬‬ ‫‪08 : 47‬‬ ‫‪$‬‬ ‫فرمان ‪ s‬يك جای خالي را جايگزين مي‌کند و هر چیزی را که تا فاصله بعدی توسط يك فاصله تنها به دنبال آن مي‌آيد (تا جايي که‬

‫امکان‌پذير است شامل اکثر فاصله‌ها مي‌باشد)‪ .‬دوباره نقل‌قولها لزم هستند‪.‬‬

‫تقريبا همان فرمان ‪ sed‬مي‌تواند برای ايجاد يك برنامه ‪ getname‬استفاده شود که نام کاربر شما را بر مي‌گرداند ‪:‬‬

‫‪$ cat getname‬‬ ‫‪who am : | sed ′ s / . * // ′‬‬ ‫‪$ getname‬‬ ‫‪you‬‬ ‫‪$‬‬

‫توالي ديگر ‪ sed‬که غالباً استفاده مي‌شود اين است که ما آن را در يك فايل شل با عنوان ‪ ind‬ساخته‌ايم‪ .‬فرمان ‪ ،ind‬درورودی خود يك‬


‫محیط برنامه سازی لینوکس‬

‫‪102/322‬‬

‫ايست جدول‌بندی را فاصله‌گذاری مي‌کند؛ اين فرمان برای حرکت دادن چیزی به منظور ايجاد تناسب بهتر بر روی صفحه چاپگر سطر‬ ‫مفید و مناسب است‪.‬‬

‫اجرای ‪ ind‬آسان است ـ يك جدول بندی در جلوی هر سطر بچسبانید ‪:‬‬

‫‪* $ sed ′ s / ^ / → / ′‬‬ ‫نسخه ‪ 1‬از ‪ind‬‬ ‫اين نسخه يك جدول‌بندی را بر روی هر سطر خالي نیز قرار مي‌دهد که به نظر غیرضروری مي‌رسد‪ .‬يك نسخه بهتر از توانايي ‪sed‬‬ ‫برای انتخاب سطرهايي استفاده مي‌کند که بايد تغییر داده شوند‪ .‬اگر شمايك طرح برای فرمان به صورت پیشوندقرار دهید‪ ،‬فقط‬

‫سطرهايي که طرح را تطبیق مي‌کنند تحت تأثیر قرار مي‌گیرند ‪:‬‬

‫‪* $ sed ′ /.s / ^ / → / ′‬‬ ‫نسخه ‪ ۲‬از ‪ind‬‬ ‫طرح ‪ ، /. /‬هر سطری را تطبیق مي‌دهد که حداقل دارای يك کاراکتر بر روی خود غیر از يك سطر جديد مي‌باشد؛ فرمان ‪ s‬برای آن‬

‫سطرها انجام مي‌شود اما برای سطرهای خالي اجرا نمي‌شود‪ .‬به خاطر داشته باشید که ‪ ، sed‬همه سطرها را بدون توجه به اينکه آيا آنها‬ ‫تغییر کرده‌اند يا نه‪ ،‬خارج مي‌کند‪ ،‬در نتیجه سطرهای خالي به همان صورتي به وجود مي‌آيند که بايد باشند‪.‬‬

‫هنوز يك راه ديگر برای نوشتن ‪ ind‬وجود دارد‪ .‬اين امکان وجود دارد که فرمانها فقط بر روی سطرهايي انجام شوند که طرح منتخب‬

‫را تطبیق نمي‌کنند‪ ،‬با قرار دادن يك علمت تعجب ! قبل از فرمان‪ .‬در‬

‫‪* $ sed ′/ ^ $ / ! s / ^ / → / ′‬‬ ‫نسخه ‪ ۳‬از ‪ind‬‬ ‫طرح ‪ ، /$ ^ /‬سطرهای خالي را تطبیق مي‌دهد (انتهای سطر سريعا با آغاز سطر دنبال مي‌شود) ‪ ،‬بنابراين ‪ ، says ! / $ ^ /‬فرمان را بر‬

‫روی سطرهای خالي اجرا نمي‌کند‪.‬‬

‫همانگونه که در بال گفتیم ‪ ،sed ،‬هر سطر را به طور اتوماتیك پرينت مي‌کند‪ ،‬بدون توجه به اينکه چه چیزی درخصوص آن انجام شده‬

‫است (مگر اينکه حذف شود)‪ .‬به علوه ‪ ،‬اکثر فرمانهای ‪ ed‬مي‌توانند استفاده شوند‪ .‬بنابراين‪ ،‬نوشتن يك برنامه ‪ sed‬که سر سطر اول‬ ‫ورودی خود (‪ )say‬را پرينت مي‌کند‪ ،‬آسان است‪ ،‬سپس از سیستم خارج شويد ‪:‬‬

‫‪sed 3 q‬‬ ‫اگر چه ‪ 3q‬يك فرمان ‪ ed‬مجاز نمي‌باشد‪ ،‬اما در ‪ sed‬حس بوجود مي‌آورد ‪:‬‬

‫سطرهای کپي‪ ،‬در نتیجه پس از سومین فرمان از سیستم خارج مي‌شوند‪.‬‬

‫شما مي‌خواهید پردازش ديگری را برای داده‌ها انجام دهید‪ ،‬مانند گذاشتن فاصله (تورفتگي) برای آن‪ .‬يك راه برای انجام اين کار‪،‬‬ ‫اجرای خروجي از ‪ sed‬از طريق ‪ ind‬مي‌باشد‪ ،‬اما چون ‪ sed‬فرمانهای متعدد را مي‌پذيرد‪ ،‬چنین چیزی را مي‌توان با يك درخواست تنها‬

‫(که تا حدودی بعید به نظر مي‌رسد) از ‪ sed‬انجام داد ‪:‬‬

‫‪′s/^/→/‬‬

‫‪sed‬‬ ‫‪3q′‬‬

‫توجه به جايي که نقل قولها و سطر جديد قرار دارند‪ ،‬داشته باشید ‪ :‬فرمانها بايد بر روی سطرهای مجزا باشند‪ .‬اما ‪ sed‬فاصله‌های اصلي‬ ‫و جدول بندی‌ها را ناديده مي‌گیرد‪.‬‬

‫با اين عقايد‪ ،‬نوشتن يك برنامه با عنوان ‪ ،head‬برای پرينت سطرهای اولیه از هر آرگومان اسم فايل‪ ،‬محسوس به نظر مي‌رسد‪ .‬اما ‪sed‬‬

‫‪( 3q‬با ‪ )10q‬برای تايپ کردن آنقدر آسان است که ما هرگز نیاز آن را حس نکرده‌ايم‪ .‬اما‪ ،‬ما يك ‪ ind‬اجرا مي‌کنیم‪ ،‬چون فرمان ‪sed‬‬

‫معادل آن برای تايپ‪ ،‬دشوارتر است‪( .‬در فرآيند نوشتن اين کتاب ما برنامه ‪ ۳۰‬سطری ‪ c‬را با دومین نسخه از اجراهای يك سطری که‬


‫محیط برنامه سازی لینوکس‬

‫‪103/322‬‬

‫قبل نشان داده شده است‪،‬جايگزين کرديم)‪ .‬ملك آشکاری در اين خصوص وجود ندارد که چه موقع ايجاد يك فرمان مجزا از يك‬

‫سطر فرمان پیچیده با ارزش است؛ بهترين قاعده‌ای که ما پیدا کرده‌ايم‪ ،‬قرار دادن آن د ر ‪ bin‬خود و مشاهده استفاده واقعي از آن‬ ‫مي‌باشد‪.‬‬

‫همچنین اين امکان وجود دارد که فرمانهای ‪ sed‬را در يك فايل قرار دهیم و آنها را از آنجا با فرمان‬

‫‪$‬‬ ‫اجرا کنیم‪.‬‬

‫‪… sed – f cmd file‬‬

‫شما مي‌توانید از گزينش گران سطر غیر از اعدادی مانند ‪ ۳‬استفاده کنید ‪:‬‬

‫ورودی خود را پرينت مي‌کند و دارای طرح تطبیق کننده اولین سطر مي‌باشد و‬

‫‪sed ′ / pattern / q′‬‬

‫‪$‬‬

‫‪$ sed ′ / pattern / d ′‬‬ ‫هر سطری را که شامل ‪ pattern‬باشد‪ ،‬حذف مي‌کند؛ حذف قبل از اينکه سطر به طور اتوماتیك پرينت شود رخ مي‌دهد‪ ،‬در نتیجه‬

‫سطرهای حذف شده ‪ ،‬جدا مي‌شوند‪.‬‬

‫اگر چه پرينت خودکار معمول ً مناسب مي‌باشد‪ ،‬اما گاهي اوقات نیاز به روش دارد‪ .‬پرينت خودکار مي‌تواند با انتخاب ‪ ، c-n‬خاموش‬

‫شود؛ در اين حالت‪ ،‬فقط سطرهايي که آشکارا با يك فرمان ‪ P‬پرينت مي‌شوند در خروجي ظاهر مي‌شوند‪.‬‬

‫‪ ،‬براي مثال‬ ‫‪$ sed – n ′ / pattern / p′‬‬ ‫كاري را انجام مي‌دهد كه ‪ grep‬انجام مي‌دهد‪ .‬چون شرايط تطبيق مي‌تواند با دنبال شدن‬ ‫‪sed – n ′ / pattern / ! p′ $‬‬ ‫آن با ! معكوس شود‪ ،‬در نتيجه‬ ‫يك ‪ grep – v‬مي‌باشد (و در نتيجه فرمان ‪ sed ′ / pattern / d′‬مي‌باشد)‪.‬‬ ‫چرا ما هر دوی ‪ sed‬و ‪ grep‬را داريم؟ بعد از همه اين موارد‪ grep ،‬فقط يك مورد خاص از ‪ sed‬مي‌باشد‪ .‬بخشي از علت آن به خاطر‬

‫تاريخچه آن مي‌باشد ـ ‪ grep‬قبل از ‪ sed‬آمد‪ .‬اما ‪ grep‬باقي مي‌ماند و به راستي توسعه مي‌يابد‪ ،‬چون برای کار ويژه‌ای که هر دوی آنها‬ ‫انجام مي‌دهند‪ ،‬اساساً استفاده از ‪ sed‬آسانتر است ‪ ، grep :‬مورد عمومي تا جايي که امکان دارد به طور مختصر انجام مي‌دهد‪، grep( .‬‬

‫همچنین کارهای ديگری را که ‪ sed‬انجام نمي‌دهد‪ .‬انجام مي‌دهد ‪ :‬برای نمونه به انتخاب ‪ -b‬نگاه کنید)‪ .‬اما برنامه‌ها از بین مي‌روند‪.‬‬

‫زماني برنامه‌ای وجود داشت که ‪ gres‬نامیده مي‌شد و جايگزيني ساده را انجام مي‌داد‪ ،‬اما تقريبا خیلي سريع منقضي شد‪ ،‬زماني که ‪sed‬‬ ‫بوجود آمد‪.‬‬

‫سطرهای جديد مي‌توانند با ‪ sed‬و با استفاده از همان نحو ‪ ed‬درج شوند‪:‬‬

‫\ ‪$ sed ′ s / $ /‬‬ ‫‪>/′‬‬

‫يك سطر جديد را به انتهاي هر سطر اضافه مي‌كند‪ ،‬در نتيجه فاصله دوبل به ورودي آن‬ ‫اضافه مي‌شود و‬

‫‪′ s / ] →[ ]→ $‬‬

‫‪\ / * ]sed‬‬ ‫<‪g′/‬‬

‫هر رشته از فاصله‌هاي خالي يا جدول‌بندي‌ها را با يك سطر جديد جايگزين مي‌كند و در‬


‫محیط برنامه سازی لینوکس‬

‫‪104/322‬‬

‫نتيجه ورودي خود را در يك كلمه در هر سطر‪ ،‬تقسيم مي‌كند‪( .‬عبارت منظم ' [→] ' ‪ ،‬يك‬ ‫فاصله يا جدول‌بندي را تطبيق مي‌كند ؛ ‘ [→] * ' تعداد صفر يا چند تا از اين فاصله‌ها يا‬ ‫جدول‌بندي‌ها را تطبيق مي‌كند‪ ،‬بنابراين كل طرح يك يا چند فاصله و يا چند جدول‌بندي را‬ ‫تطبيق مي‌كند‪.‬‬ ‫همچنین شما مي‌توانید جفت‌هايي از عبارات منظم يا شماره‌های سطر را برای انتخاب يك دامنه از سطرهايي بکار ببريد که بر روی آنها‬ ‫يکي از فرمانها عمل مي‌کنند‪.‬‬

‫فقط از ‪ ۲۰‬تا ‪ ۳۰‬سطر را پرينت كنيد‬

‫‪- n ′ 20 , 30 p′ $‬‬

‫سطرهاي ‪ ۱‬تا ‪ ۱۰‬را حذف كنيد (‪tail =( +11‬‬

‫‪′ 1 , 10 d ′‬‬

‫تا جايي حذف كنيد كه فقط يك سطر خالي باشد‬ ‫هر گروه از سطرها را از يك سطر خالي‬

‫‪$ sed‬‬

‫‪′ 1 , /^ $/ d ′‬‬

‫‪$‬‬

‫‪sed‬‬

‫‪sed‬‬

‫‪sed - n ′ / ^ $ / , / ^ end / p′ $‬‬

‫تا سطري كه با ‪ end‬آغاز مي‌شود پرينت كنيد‬ ‫آخرين سطر را حذف كنيد‪.‬‬

‫‪$‬‬

‫‪′$d′‬‬

‫‪sed‬‬

‫شماره‌های سطر از آغاز ورودی مي‌آيند؛ آنها در آغاز يك سطر جديد رسیت نمي‌شوند‪ .‬اما يك محدوديت مهم از ‪ sed‬وجوددارد که‬

‫مشترك با ‪ ed‬نمي‌باشد ‪ :‬شماره‌های نسبي سطر حفظ نمي‌شوند‪ .‬بويژه ‪ + ،‬و … در عبارتهای شماره سطر درك نمي‌شوند‪ ،‬بنابراين‪،‬‬

‫رسیدن به عقب‌روها در ورودی امکان‌پذير نمي‌باشد‪.‬‬

‫نمي‌تواند به عقب رو استناد شود ‪ :‬غيرمجاز‬

‫‪$‬‬

‫‪sed ′ $ - 1 d ′‬‬ ‫‪ d‬فرمان شناسايي نشده ‪1 - $ :‬‬ ‫‪$‬‬

‫زماني که يك سطر خوانده مي‌شود‪ ،‬سطر قبلي برای همیشه پاك مي‌شود ‪ :‬هیچ راهي برای شناسايي سطر بعد از قبلي وجود ندارد‪،‬‬ ‫يعني چیزی که اين فرمان نیاز دارد‪( .‬به طور عادلنه‪ ،‬يك راه برای کارکردن آن با ‪ sed‬وجود دارد‪ ،‬اما اين راه خیلي پیشرفته است‪ .‬به‬

‫فرمان « ‪ »hold‬در کتاب راهنما مراجعه کنید)‪ .‬همچنین راهي برای انجام نشاني دهي نسبي به طرف جلو وجود ندارد‪:‬‬

‫نمي‌تواند به جلورو استناد شود ‪ :‬غیر مجاز‬

‫‪ ، sed‬توانايي خواندن بر روی فايلهای خروجي متعدد را فراهم مي‌کند‪ .‬برای مثال ‪،‬‬

‫‪sed ′ / thing / + d′‬‬

‫‪′ / pat / w file /‬‬ ‫… ‪/ pat / ! w file r′ filenames‬‬

‫‪sed – n‬‬

‫‪$‬‬ ‫‪$‬‬

‫سطرهايي را مي‌نويسد که ‪ pat‬روی فايل ‪ 1‬را تطبیق مي‌دهند و سطرهايي که ‪ pat‬روی فايل ‪ ۲‬را تطبیق نمي‌دهند‪ .‬يا برای مشاهده‬ ‫مجدد اولین مثال‌ ما ‪،‬‬


‫محیط برنامه سازی لینوکس‬

‫‪105/322‬‬

‫‪sed ′ s / unix / unix )Tm( / gw u.04 t ′ filenames … > output‬‬ ‫کل خروجي را برای خروجي فايل همانند قبل مي‌نويسد‪ ،‬اما همچنین فقط سطرهای تغییر يافته برای فايل ‪ u .out‬را نیز مي‌نويسد‪.‬‬

‫‪$‬‬

‫گاهي اوقات‪ ،‬همکاری با شل برای قرادادن آرگومانهای فايل شل در وسط يك فرمان ‪ sed‬لزم است‪ .‬يك مثال در اين خصوص ‪ ،‬برنامه‬

‫‪ newer‬مي‌باشد که همه فايلهايي را در يك فهرست لیست مي‌کند که جديدتر از فايلهای خاص مي‌باشند‪.‬‬

‫‪$ cat newer‬‬ ‫‪# newer f : list files newer than f‬‬ ‫‪Is – t : sed ′ / ^ ′ $ | ′ $ / q′‬‬ ‫‪$‬‬

‫نقل قولها‪ ،‬از کاراکترهای خاص و متعدد هدف دار در ‪ sed‬محافظت مي‌کنند؛ زماني که در معرض حذف ‪ 1 $‬قرار مي‌گیرند‪ ،‬در نتیجه‬

‫شل آن را با اسم فايل جايگزين مي‌کند‪ .‬يك روش ديگر برای نوشتن آرگومان به اين شکل مي‌باشد ‪:‬‬

‫‪″/^$|\$q″‬‬ ‫چون ‪ / $‬با آرگومان جايگزين مي‌شود زماني که \ ‪ $‬فقط به ‪ $‬تبديل مي‌شود‪ .‬به همین روش‪ ،‬ما مي‌توانیم ‪ older‬را بنويسیم که همه‬

‫فايلهای قديمي‌تر از فايلهای نامگذاری شده را لیست مي‌کند ‪:‬‬

‫‪$ cat older‬‬ ‫‪# older f : list files older than f‬‬ ‫‪Is – tr | sed ′ / ^ ′ $ | ′ $ / q′‬‬

‫تنها تفاوت انتخاب ‪ - r‬بر روی ‪ IS‬برای معکوس کردن ترتیب‪ ،‬مي‌باشد‪.‬‬

‫جدول‪ : ۴.۲  ‬خلاصه‪ ‬فرمانهاي ‪sed‬‬ ‫سطرها را تا جايي به خروجي پيوست مي‌دهد كه هيچ سطري با \ به پايان نرسد‬ ‫\‪a‬‬

‫‪/‬‬ ‫‪b /abe‬‬ ‫انتقال به فرمان ‪abe// :‬‬ ‫‪\c‬‬ ‫سطرها را به متن بعدي به صورت ‪ a‬تغيير مي‌دهد‬ ‫‪d‬‬ ‫سطر را حذف مي‌كند؛ سطر ورودي بعدي را مي خواند‬ ‫‪i/‬‬ ‫متن بعدي را قبل از خروجي بعدي اينسرت مي‌كند‪.‬‬ ‫سطر را فهرست‌بندي مي‌كند‪ ،‬همه كاراكترهاي غير پريتر را مرئي مي‌كند ‪l‬‬ ‫‪p‬‬ ‫سطر را پرينت مي‌كند‬ ‫‪q‬‬ ‫از سيستم خارج مي‌شود‬ ‫‪r file‬‬ ‫فايل را مي‌خواند‪ ،‬محتواهاي آن را براي خروجي كپي مي‌كند‬ ‫‪s / old / new / f‬‬ ‫‪ New‬را با ‪ old‬جايگزين مي‌كند‪ .‬اگر ‪ ،f = g‬همه‬ ‫رخدادها را جايگزين مي‌كند ؛ ‪ . f = p‬پرينت مي‌كند؛ ‪، f = wfile‬‬ ‫فايل را مي‌خواند‪.‬‬ ‫امتحان ‪ :‬انقال به ‪ /abp/‬انجام مي‌شود اگر جايگزيني براي سطر خللي انجام شود‪.‬‬ ‫‪/t /abe‬‬ ‫‪wfile‬‬ ‫سطر را براي فايل مي‌نويسد‬ ‫‪/y / strl / str 2‬‬ ‫هر كاراكتر از ‪ strl‬را با كاراكتر مطابق از ‪ str2‬جايگزين‬ ‫مي‌كند (مراتب مجاز نيستند)‬

‫شماره سطر ورودي فعلي را پرينت مي‌كند‬ ‫‪ sed cmd‬را انجام مي‌دهد فقط اگر سطر انتخاب نشود‬ ‫‪ / abe /‬را براي فرمانهاي ‪ b‬و ‪ t‬تعيين مي‌كند‬

‫=‬ ‫! ‪cmd‬‬ ‫‪/ abe / :‬‬


‫محیط برنامه سازی لینوکس‬

‫‪106/322‬‬

‫فرمانها را تا تطبيق } به عنوان يك گروه بررسي مي‌كند‬

‫}‬

‫اگرچه ‪ ،sed‬خیلي بیشتر از چیزهايي که شرح داديم انجام مي‌دهد‪ ،‬شامل بررسي شرايط‪ ،‬حلقه‌سازی و منشعب کردن‪ ،‬به خاطر آوردن‬

‫سطرهای قبلي و البته بسیاری از فرمانهای ‪ ed‬که در ضمیمه ‪ ۱‬توصیف مي‌شوند ـ اما قسمت اعظم استفاده ‪ ،sed‬شبیه به چیزی است که‬

‫ما در اين جا نشان داده‌ايم ـ يك يا دو فرمان ساده ويرايش ـ و چیزی غیر از توالي‌های بلند يا پیچیده مي‌باشد‪ .‬جدول ‪ ، ۴.۲‬برخي از‬

‫توانايي‌های ‪ sed‬را به طور خلصه بیان مي‌کند‪ ،‬اگر چه ‪ ،‬عملکردهای چند سطری در اين جدول حذف است‪.‬‬

‫‪ Sed‬مناسب و آسان است چون به صورت اختیاری مي تواند با ورودی‌های بلند کار کند‪ ،‬چون سريع است و چون شبیه به ‪ ed‬با‬

‫عبارتهای منظم و پردازش يك سطر در يك زمان آن مي‌باشد‪ .‬اما روی ديگر سکه‪ sed ،‬ـ يك شکل نسبتا محدود از حافظه را فراهم‬ ‫مي‌کند (به خاطر آوردن متن از يك سطر تا سطری ديگر دشوار است)‪ sed ،‬فقط يك عبور از داده‌ها را امکان‌پذير مي‌سازد‪ ،‬برگشتن به‬

‫عقب امکان پذير نمي‌باشد‪ ،‬راهي برای انجام ارجاعات به سمت جلو مانند ‪ ، / … / +1‬وجود ندارد و ‪ sed‬تسهیلتي را برای کار‬ ‫کردن با شماره‌ها فراهم نمي‌کند ـ ‪ sed‬صرف ًا يك ويراستار متن مي‌باشد‪.‬‬

‫تمرين ‪ Older .۴. ۵‬و ‪ Newer‬را به گونه‌ای تغییر دهید که ديگر دارای فايل آرگومان در خروجي خود نباشند‪ .‬آنها را به گونه‌ای تغییر‬ ‫دهید که فايلها در يك ترتیب مخالف فهرست‌بندی شوند‪.‬‬

‫تمرين ‪ .۴.۶‬از ‪ sed‬برای استحکام ‪ bundle‬استفاده کنید‪ .‬توجه ‪ :‬در اسناد موجود در اينجا ‪ ،‬کلمه نشان پايان‪ ،‬فقط زماني شناسايي‬ ‫مي‌شود که سطر را به طور دقیق تطبیق کند‪.‬‬

‫‪ ۴.۴‬پويش طرح ‪ awk‬و زبان پردازش‬

‫برخي از محدوديتهايت ‪ ، sed‬توسطت ‪ awk‬برطرف مي‌شوند‪ .‬طرح مربوط بهت ‪ ، awk‬تا حدود‬ ‫زيادي شبيه بهت ‪ sed‬مي‌باشد‪ ،‬اما جزئيات آن بيشتر بر اساس زبان برنامه‌نويسي ‪ c‬مي‬ ‫‪$‬‬ ‫باشند تا يك ويراستار متن‪ .‬استفاده از ‪ awk‬درست شبيه به ‪ sed‬مي‌باشد ‪:‬‬ ‫‪…awk ′program′ filenames‬‬ ‫اما برنامه متفاوت است ‪:‬‬

‫{ ‪pattern } action‬‬ ‫{ ‪pattern } action‬‬ ‫…‬ ‫‪ ،awk‬ورودی را در اسامي فايل‪ ،‬در هر زمان يك سطر‪ ،‬مي‌خواند‪ .‬هر فايل با هر طرح به اين ترتیب مقايسه مي‌شود؛ برای هر طرحي‬ ‫که سطر را تطبیق مي‌کند‪ ،‬عملکرد مطابق با آن انجام مي‌شود‪ awk .‬همانند ‪ ، sed‬فايلهای ورودی خو درا تغییر نمي‌دهد‪.‬‬

‫طرحها مي‌توانند عبارتهای منظم‪ ،‬دقیقاً مانند عبارتهای ‪ egrep‬باشند‪ ،‬يا مي‌توانند دارای شرايط پیچده‌تر و يادآور ‪ c‬باشند‪ .‬به عنوان يك‬ ‫مثال ساده‪ ،‬اگر چه‬

‫… ‪′/ regular expressino / } print{ ′ filenames‬‬ ‫اما کاری را انجام مي‌دهد که ‪ egrep‬انجام مي‌دهد ‪ :‬اين عبارت هر سطری را پرينت مي‌کند که عبارت منظم را تطبیق مي‌کند‪.‬‬

‫‪awk‬‬

‫‪$‬‬

‫طرح يا عملکرد انتخابي مي‌باشند‪ .‬اگر عملکرد حذف شود‪ ،‬عملکرد پیش فرض سطرهای تطبیق شده را پرينت مي‌کند‪ ،‬بنابراين‬ ‫… ‪′ / regular expression / ′ filenames‬‬

‫‪$ awk‬‬


‫محیط برنامه سازی لینوکس‬

‫‪107/322‬‬

‫همان کاری را انجام مي‌دهد که مثال قبلي انجام مي‌دهد ‪ .‬به طور معکوس‪ ،‬اگر طرح حذف شود‪ .‬در نتیجه بخش عملکرد برای هر سطر‬ ‫ورودی انجام مي‌شود ‪ .‬بنابراين‬

‫… ‪′} print{ ′ filenames‬‬

‫چیزی را انجام مي‌دهد که ‪ cat‬انجام مي‌دهد‪ ،‬ولو اينکه کندتر انجام مي‌دهد‪.‬‬

‫‪awk‬‬

‫‪$‬‬

‫و اما نکته نهايي ‪ ،‬قبل از اينکه به مثالهای جالب بپردازيم‪ .‬همانند ‪ ،sed‬اين امکان وجود دارد که برنامه را برای ‪ awk‬از يك فايل ارائه‬

‫دهیم ‪:‬‬

‫‪filenames ….‬‬

‫‪awk – f cmd file‬‬

‫‪$‬‬

‫ميدان‌ها‬ ‫‪ awk‬به طور خودکار هر سطر ورودی را به میدانها تقسیم مي‌کند‪ ،‬يعني رشته‌هايي از کاراکترهای بدون فاصله که توسط فاصله‌ها يا‬ ‫جدول‌بندی‌ها از هم جدا مي‌شوند‪ .‬با اين تعريف ‪ ،‬خروجي ‪ who‬دارای پنج میدان مي‌باشد ‪:‬‬

‫‪11 : 35‬‬ ‫‪11 : 27‬‬

‫‪sep 29‬‬ ‫‪sep 29‬‬

‫‪tty 2‬‬ ‫‪tty 4‬‬

‫‪who‬‬ ‫‪you‬‬ ‫‪jim‬‬

‫‪$‬‬

‫‪$‬‬ ‫‪ awk‬میدانهای ‪ $2 ، $1‬و … ‪ ، NF $‬را مي‌خواند‪ NF ،‬متغیری است که ارزش آن برای تعداد میدانها معین مي‌شود‪ .‬در اين مورد ‪،‬‬

‫‪ NF‬برای هر دو سطر ‪ ۵‬مي‌باشد ‪( .‬به تفاوت بین ‪ ، NF‬عداد میدان‌ها و ‪ ،$ NF‬يعني آخرين میدان بر روی سطر توجه کنید‪ .‬در ‪،awk‬‬ ‫بر خلف شل‪ ،‬فقط میدانها با يك ‪ $‬آغاز مي‌شوند؛ متغیرها ساده هستند)‪ .‬برای مثال‪ ،‬برای جدا کردن اندازه‌های فايل ايجاد شده توسط‬

‫‪du-a‬‬ ‫و برای پرينت اسامي افراد وارد شده به سیستم و زمان ‪ ، login‬در يك سطر ‪:‬‬

‫‪du – a | awk ′ } print $ 2 {′‬‬ ‫‪who | awk ′ } print $ 1 , $ 5 {′‬‬ ‫‪you‬‬ ‫‪11 : 53‬‬ ‫‪jim‬‬ ‫‪11 : 27‬‬

‫برای پرينت نام و زمان ‪ login‬ترتیب بندی شده توسط زمان ‪:‬‬

‫‪′ } print $ 5 , $ 1 {′ | sort‬‬

‫‪who | awk‬‬

‫‪$‬‬ ‫‪$‬‬ ‫‪$‬‬ ‫‪$‬‬

‫‪11 : 27 jim‬‬ ‫‪11 : 53 you‬‬ ‫‪$‬‬ ‫راهکارهای ديگری برای نسخه‌های ‪ sed‬وجود دارند که قبل در اين فصل ارائه شدند‪ .‬اگر چه ‪ awk‬آسانتر از ‪ sed‬برای عملکردهايي‬

‫مانند اين‌ها‪ ،‬قابل استفاده مي‌باشد‪ ،‬اما معمولً کندتر است و هر دو آغاز به کار و اجرا مي‌کنند زماني که ورودی زيادی وجود دارد ‪awk .‬‬

‫در حالت عادی به صورت فضای سفید (هر تعداد از فاصله‌ها يا جدول بندی‌ها) ‪ ،‬میدانهای مجزا‪ ،‬تصور مي‌شود‪ ،‬اما جداساز مي‌تواند‬

‫برای هر کاراکتر مفرد تغییر کند‪ .‬يك روش برای تغییر‪ ،‬انتخاب سطر فرمان ‪( -F‬مورد باليي) مي‌باشد‪ .‬برای مثال‪ ،‬میدانهای موجود در‬


‫محیط برنامه سازی لینوکس‬

‫‪108/322‬‬

‫فايل کلمه رمز ‪ ، etc / passwd /‬توسط «دو نقطه‌ها» از هم جدا مي‌شوند‪.‬‬

‫‪$ sed 3 g / etc / passwd‬‬ ‫‪root : 30 . FHR 5 KOB. 3 s : 0 : 1 : S . user : / :‬‬ ‫‪ken : y – 68 wd 10 ijayz : 6 : 1 : k . Thompson : / usr / ken :‬‬ ‫‪dmr ; z 4 a 3 d j w bg v w c k : v : 1 : D-M. Ritchie : / usr / dmr :‬‬ ‫‪$‬‬ ‫برای پرينت کردن اسامي کاربرها‪ ،‬که از اولین میدان مي‌آيند ‪،‬‬

‫‪$ sed 3 q / etc / passwd | awk – f : ′ } print $ 1{ ′‬‬ ‫‪root‬‬ ‫‪ken‬‬ ‫‪dmr‬‬ ‫‪$‬‬ ‫استفاده از فاصله‌ها وجدول‌بندی‌ها‪ ،‬تعمدا ً خاص مي‌باشد‪ .‬توسط پیش فرض‪ ،‬هم فاصله‌ها و هم جدول‌بندی‌ها‪ ،‬جداساز هستند و‬ ‫جداسازهای اصلي جدا مي‌شوند‪ .‬اگر جداساز‪ ،‬برای هر چیزی غیر از فاصله تنظیم شود‪ ،‬در نتیجه‪ ،‬جداسازی‌های اصلي در تعیین‬

‫میدانها‪ ،‬به حساب آورده مي‌شوند‪ .‬در اصل‪ ،‬اگر جداساز‪ ،‬يك جدول بندی باشد‪ ،‬در نتیجه فاصله‌ها‪ ،‬کاراکترهای جداساز نمي‌باشند‪.‬‬

‫فاصله‌های اصلي بخشي از میدان مي‌باشند و هر جدول بندی‪ ،‬يك میدان را تعريف مي‌کند‪.‬‬

‫چاپ‬ ‫‪ ، awk‬رد کمیتهای جالب را در کنار تعداد میدانهای ورودی حفظ مي‌کند‪ .‬متغیر توکارـ ‪ ، NR‬تعداد رکورد ورودی جاری يا سطر‬ ‫مي‌باشد‪ .‬در نتیجه برای افزودن تعداد سطرها به يك جريان ورودی ‪ ،‬از عبارت زير استفاده کنید ‪:‬‬

‫‪$ awk ′ } print NR , $ o {′‬‬ ‫میدان ‪ ، $0‬کل سطر ورودی ‪ ،‬بدون تغییر مي‌باشد‪ .‬در يك بیان ‪ ،print‬اقلم که توسط کاماها از هم جدا مي‌شوند‪ ،‬به طور مجزا توسط‬

‫جداساز میدان خروجي چاپ مي‌شوند که توسط پیش‌فرض‪ ،‬يك فاصله خالي مي‌باشد‪.‬‬

‫فرمت کردن که ‪ print‬آن را انجام مي‌دهد‪ ،‬اغلب قابل قبول مي‌باشد‪ ،‬اما اگر قابل قبول نباشد‪ ،‬شما مي‌توانید از يك بیان با عنوان ‪print‬‬

‫‪ f‬برای کنترل کامل خروجي خود استفاده کنید‪ .‬برای مثال‪ ،‬برای چاپ تعداد سطرها در يك میدان با چهار رقم پهنا‪ ،‬شما مي‌توانید از‬ ‫عبارت زير استفاده کنید‪:‬‬

‫‪awk ′ } print f ″ % 4 d % s \ n ″ , nR , $o {′‬‬ ‫‪ 4d %‬يك عدد صحیح دهدهي (‪ )NR‬را در يك میدان با چهار رقم پهنا‪ ،‬مشخص مي‌کند‪ S % ،‬يك رشته ازکاراکترها (‪ )$0‬را و ‪\n‬‬ ‫‪$‬‬

‫يك کاراکتر از سطر جديد را مشخص مي‌کنند‪ ،‬چون ‪ ،print f‬هیچ فاصله يا سطر جديدی را به طور خودکار چاپ نمي‌کند‪ .‬بیان ‪print‬‬

‫‪ f‬در ‪ awk‬شبیه عملکرد ‪ c‬مي‌باشد; به ‪ )print f )۳‬مراجعه کنید‪.‬‬

‫ما توانستیم اولین نسخه ‪( ind‬از ابتدا در اين فصل) را به صورت زير بنويسیم‬ ‫که يك جدول‌بندی ( ‪ )\ t‬و رکورد ورودی را چاپ مي‌کند‪.‬‬

‫* ‪awk ′ } print f ″ \ t % s \ n ″ , $o { ′ $‬‬


‫محیط برنامه سازی لینوکس‬

‫‪109/322‬‬

‫طرح‌ها‬ ‫فرض کنید شما مي‌خواهید به عبارت ‪ etc / passwd /‬در جستجوی افرادی باشید که دارای هیچ گونه کلمه رمزی نمي‌باشند‪ .‬کلمه رمز‬

‫رمزی شده‪ ،‬دومین میدان مي‌باشد‪ ،‬بنابراين برنامه‪ ،‬فقط يك طرح مي‌باشد ‪:‬‬

‫‪$ awk – f : ′ $ 2 = = ″ ″ ′ / etc / passwd‬‬ ‫طرح درخواست مي‌کند که آيا دومین میدان‪ ،‬يك رشته خالي است ( ‘ = = ’ ‪ ،‬عملگر تست تساوی مي‌باشد) شما مي‌توانید اين طرح را‬

‫به روشهای متعدد بنويسید ‪:‬‬

‫دومين ميدان خالي است‬ ‫دومين ميدان‪ ،‬رشته خالي را تطبيق مي‌كند‬ ‫دومين ميدان هيچ كاراكتري را تطبيق نمي‌كند‬ ‫طول دومین میدان صفر است‬

‫‪″ ″==2 $‬‬ ‫‪/$^/∼2 $‬‬ ‫‪/./ ∼!2 $‬‬ ‫‪= = )0length )$ 2‬‬

‫علمت ‪ ، ‬تطبيق عبارت منظم را نشان مي‌دهد و به ! به معناي « تطبيق نمي‌كند» مي‌باشد‪ .‬عبارت‬ ‫منظم خودش ضميمه اسلش‌ها مي‌شود‪.‬‬ ‫‪ ، length‬يك عملکرد توکار از ‪ awk‬مي‌باشد که طول يك رشته از کاراکترها را بوجود مي‌آورد‪ .‬يك طرح مي‌تواند به دنبال ! برای‬

‫منفي کردن آن بیايد‪ ،‬مانند‬

‫‘!’ يك عملگر شبیه ‪ c‬مي‌باشد‪ ،‬اما برخلف ‪ sed‬مي‌باشد‪ ،‬چون در آنجا ! پس از طرح مي‌آيد‪.‬‬

‫(‪! ) $ 2 = = ″ ″‬‬

‫يکي استفاده عمومي از طرحها در ‪ ، awk‬برای وظايف مربوط به معتبرسازی داده‌های ساده مي‌باشد‪ .‬بسیاری از اين وظايف‪ ،‬اندکي‬ ‫بیشتر از جستجوی سطرهايي مي‌باشند که معیار خود را از دست مي‌دهند؛ اگر هیچ گونه خروجي وجود نداشته باشد ‪ .‬داده‌ها قابل قبول‬

‫هستندـ (هیچ خبری‪ ،‬خبر خوبي نیست)‪ .‬برای مثال‪ ،‬طرح ‌ زير ‪ ،‬اطمینان مي‌دهد که هر رکورد ورودی که دارای تعدادی از میدانها‬ ‫مي‌باشد‪ ،‬از عملگر ‪ %‬برای محاسبه باقیمانده‪ ،‬استفاده مي‌کند‪:‬‬

‫‪# print if old number of fiflds‬‬ ‫ديگری‪ ،‬سطرهای بیش از حد طولني را‪ ،‬با استفاده از عملکرد ‪ length‬توکار چاپ مي‌کند ‪:‬‬

‫‪!=0‬‬

‫‪NF % 2‬‬

‫‪/ ength )$o( > v2 # print if too long‬‬ ‫‪ ، awk‬از همان تبديل کامنت‪ ،‬همانند شل استفاده مي‌کند ‪ :‬يك ‪ . #‬ابتدای کامنت را علمت‌گذاری مي‌کند‪.‬‬

‫شما مي‌توانید خروجي را تا حدودی آگاهي دهنده‌تر‪ ،‬از طريق چاپ يك اخطار و بخشي از سطر بي‌نهايت وطولني و با استفاده از يك‬ ‫عملکرد توکار ديگر ‪ ، substr ،‬بسازيد ‪:‬‬

‫‪length )$o( > v2 }print ″ line ″ , NR , ″too long : ″ , substr‬‬ ‫(‪)$o , 1 , 4‬‬ ‫(‪ ، s , m , n( substr‬رشته فرعي ‪ s‬را مي‌سازد که در موقعیت ‪ m‬آغاز مي‌شود و ‪ n‬کاراکتر طولني مي‌باشد‪( .‬رشته در موقعیت ‪ 1‬آغاز‬ ‫مي‌شود)‪ .‬اگر ‪ n‬حذف مي‌شود‪ ،‬رشته فرعي از ‪ m‬تا پايان‪ ،‬استفاده مي‌شود‪ ،Substr .‬نیز مي‌تواند برای استخراج میدانهای دارای موقعیت‬ ‫ثابت استفاده شود ‪ ،‬برای مثال‪ ،‬انتخاب ساعت و دقیقه از خروجي ‪. date‬‬

‫‪1983‬‬

‫‪$ date‬‬ ‫‪Thu sep 29 12 : 17 : 01 EDT‬‬


‫محیط برنامه سازی لینوکس‬

‫‪110/322‬‬

‫‪$ date | awk ′ } print substr ) $ 4 , 1 , 5( {′‬‬ ‫‪12 : 17‬‬ ‫‪$‬‬ ‫تمرين ‪ .۴.۷‬چند برنامه ‪ awk‬مي‌توانید بنويسید که ورودی را برای خروجي همانند کاری که ‪ cat‬انجام مي‌دهد‪ ،‬کپي کنند؟ کدام يك‬ ‫کوتاه‌ترين مي‌باشد ؟‬

‫طرحهاي ‪END , BEGIN‬‬ ‫‪ ، awk‬دو طرح خاص را بوجود مي‌آورد‪،‬ـ ‪ BEGIN‬وـ ‪ . END‬عملکردهایـ ‪ BEGIN‬قبل اينکه سطر ورودی خوانده شود‪ ،‬اجرا‬ ‫مي‌شوند ؛ شما مي‌توانید از طرح ‪ BEGIN‬برای آغاز متغیرها‪ ،‬برای چاپ عنوان‌ها و يا برای تعیین جداساز میدان با نسبت دادن آن به‬ ‫متغیر ‪ FS‬استفاده کنید ‪:‬‬

‫{ ‪′ BEGIN } FS = ″ : ″‬‬ ‫‪$2 = = ″ ″ ′ / etc/passwd‬‬

‫ما از همه رمزهاي عبور استفاده مي‌كنيم ‪ :‬خروجي ندارد‬

‫‪$ awk‬‬ ‫>‬

‫‪$‬‬

‫عملكردهاي‬ ‫‪ ، END‬پس از پردازش آخرين سطر ورودي‪ ،‬انجام مي‌شوند ‪:‬‬ ‫… ‪′ END } print NR{ ′‬‬

‫‪awk‬‬

‫‪$‬‬

‫تعداد سطرهاي ورودي را پرينت مي‌كند‪.‬‬ ‫حساب و متغیرها‬

‫مثالهايي که تاکنون بیان شده‌اند‪ ،‬فقط به استفاده در متن ساده پرداخته‌اند‪ .‬قدرت واقعي ‪ ،awk‬مربوط به توانايي آن برای انجام محاسبات‬

‫بر روی داده‌های ورودی مي‌باشد ؛ شمردن چیزها‪ ،‬محاسبه مجموعه‌ها و میانگین‌ها و مواردی از اين قبیل آسان است‪ .‬يك استفاده‬

‫عمومي از ‪ ،awk‬جمع کردن ستون اعداد مي‌باشد‪.‬‬

‫برای مثال ‪ ،‬برای جمع کردن همه اعداد در اولین ستون ‪:‬‬

‫{‪}s=s + $1‬‬ ‫{ ‪} prints‬‬ ‫چون تعداد ارزش‌ها در متغیر ‪ NR‬در دسترس مي‌باشد‪ .‬در نتیجه آخرين سطر را به شکل زير تغییر مي‌دهیم‬ ‫که هم مجموع و هم میانگین را چاپ مي‌کند‪.‬‬

‫{ ‪} print s , s / NR‬‬

‫‪END‬‬ ‫‪END‬‬

‫اين مثال ‪ ،‬استفاده از متغیرها در ‪ awk‬را نیز شرح مي‌دهد‪ ، S .‬يك متغیر توکار نمي‌باشد‪ .‬اما از طريق استفاده شدن ‪ ،‬تعريف مي‌شود‪.‬‬

‫متغیرها بر طبق پیش فرض با صفر شروع مي‌شوند‪ ،‬در نتیجه شما معمولً نبايد نگران آغاز باشید‪.‬‬

‫‪ awk‬نیز همان عملگرهای مختصرنويسي حساب را شبیه به ‪ c‬فراهم مي‌کند‪ ،‬بنابراين مثال آن در حالت عادی به اين صورت نوشته‬


‫محیط برنامه سازی لینوکس‬

‫‪111/322‬‬

‫مي‌شود‬

‫{‪} s + = $1‬‬ ‫‪END‬‬ ‫{ ‪} prints‬‬ ‫‪ ، S + = $1‬همانند ‪ $ + S1 = S‬مي‌باشد‪ ،‬اما از نظر نمادی ‪ ،‬فشرده‌تر مي‌باشد‪ .‬شما مي‌توانید مثالي را که به شمارش سطرهای ورودی‬ ‫مي‌پردازد مانند زير تعمیم دهید ‪:‬‬

‫‪} nc + = length )$o( + 1‬‬ ‫‪# number of chars 1 form \ n‬‬ ‫‪nw + = NF‬‬ ‫‪# number of words‬‬ ‫{‬ ‫‪END‬‬ ‫{ ‪} print NR , nw , nc‬‬ ‫اين عبارت سطرها‪ ،‬کلمات و کاراکترها را در ورودی خود مي‌شمارد‪ ،‬در نتیجه کار ‪ wc‬را انجام مي‌دهد (اگر چه کل‌ها را توسط فايل‬

‫تجزيه نمي‌کند)‪.‬‬

‫به عنوان مثال ديگری از حساب‪ ،‬اين برنامه‪ ،‬تعداد صفحات ‪ 66‬سطری را که با اجرای يك مجموعه از فايلها در ‪ pr‬بوجود مي‌آيند‪،‬‬ ‫محاسبه مي‌کند‪ .‬چنین چیزی مي‌تواند در يك فرمان با عنوان ‪ ، prpages‬قرار گیرد ‪:‬‬

‫‪$ cat prpages‬‬ ‫‪# prpages : compute number of pages that pr will‬‬ ‫| * ‪print wc $‬‬ ‫{(‪awk ! / total $ / } n + = int )) $1 + 55( / 56‬‬ ‫‪END‬‬ ‫‪} print n{′‬‬ ‫‪$‬‬

‫‪ pr ، ۵۶‬سطر از متن را در روی هر صفحه قرار مي‌دهد (حقیقتي که از نظر تجربي مشخص شد)‪ .‬تعداد صفحات گرد مي‌شود‪ ،‬سپس با‬ ‫يك عملکرد توکار ‪ ،int‬به يك عدد صحیح‪ ،‬برای هر سطر از خروجي ‪ wc‬که ‪ total‬را در انتهای يك سطر تطبیق نمي‌دهد‪.‬‬

‫سر راست مي‌شود‪.‬‬

‫‪1.4‬‬ ‫‪2.4‬‬ ‫‪3.4‬‬ ‫‪4.4‬‬ ‫‪9.4‬‬

‫‪ch‬‬ ‫‪ch‬‬ ‫‪ch‬‬ ‫‪ch‬‬ ‫‪ch‬‬

‫كل‬

‫براي‬

‫‪18129‬‬ ‫‪13242‬‬ ‫‪13455‬‬ ‫‪16904‬‬ ‫‪117‬‬ ‫‪62847‬‬

‫‪$‬‬

‫* ‪wc ch 4.‬‬ ‫‪753‬‬ ‫‪3090‬‬ ‫‪612‬‬ ‫‪2124‬‬ ‫‪637‬‬ ‫‪2462‬‬ ‫‪802‬‬ ‫‪2986‬‬ ‫‪50‬‬ ‫‪213‬‬ ‫‪2854‬‬ ‫‪11172‬‬ ‫* ‪$ prpages ch 4.‬‬ ‫‪53‬‬ ‫‪$‬‬

‫اين نتيجه ‪ pr ،‬را در ‪ awk‬مستقيما اجرا كنيد ‪:‬‬ ‫‪| awk ′ End } print NR / 66{′‬‬

‫*‪pr ch 4.‬‬

‫‪$‬‬ ‫‪53‬‬ ‫‪$‬‬

‫متغيرها در ‪ awk‬نيز رشته‌هاي كاراكترها را ذخيره مي‌كنند‪ .‬اينكه آيا يك متغير به عنوان يك‬


‫محیط برنامه سازی لینوکس‬

‫‪112/322‬‬

‫عدد رفتار كند و يا به عنوان يك رشته از كاراكترها‪ ،‬به متن بستگي دارد براي صحبت‬ ‫كردن به صورت تضميني ‪ ،‬در يك عبارت حسابي مانند ‪ ، S + = $1‬ارزش عددي‪ ،‬استفاده‬ ‫مي‌شود؛ در يك متن رشته مانندت ‪ ، x = ″abc″‬ارزش رشته‪ ،‬استفاده مي‌شود؛ و در يك‬ ‫مورد مبهم مانندت ‪ ، x > y‬ارزش رشته‪ ،‬استفاده مي‌شود مگر اينكه عملوندها به وضوح‬ ‫عدديت تباشند‪( .‬قواعدت تبهت تطورت تدقيقت تدرت تكتابت تراهنمايت ‪ awk‬بيانت تمي‌شوند)‪ .‬متغيرهاي‬ ‫رشته‪،‬ت تبراي ترشته تخالي‪،‬ت تآغازت تمي‌شوند‪ .‬آمدنت تبخش‌ها‪،‬ت تمنجرت تبهت تاستفاده تخوبي تاز‬ ‫رشته‌ها مي‌شود‪.‬‬

‫‪ ،Awk‬خودش شامل تعدادی از متغیرهای توکار از هر دو نوع مي‌باشد‪ ،‬مانند ‪ NR‬و ‪.FS‬‬ ‫جدول‪ ،۴.۳‬يك فهرست کامل را ارائه مي‌دهد‪ .‬جدول ‪ ،۴.۴‬عملگرها را فهرست مي‌کند‪.‬‬

‫تمرين ‪ .۴.۸‬بررسي ما از ‪ ،prpages‬اجراهای متناوب را بیان مي‌کند‪ .‬بررسي کنید که کدام يك سريعترين مي‌باشد ‪.‬‬

‫روند كنترل‬ ‫به طور قابل توجهي ( با صحبت از تجربه)‪ ،‬ايجاد کلمات همجوار دو نسخه‌ای به طور تصادفي آسان است زماني که يك سند بزرگ‬ ‫ويرايش مي‌شود و بديهي است که چنین چیزی هرگز به طور عمودی اتفاق نمي‌افتد‪ .‬برای پیشگیری از چنین مشکلتي ‪ ،‬يکي از اجزاء‬

‫سازنده خانواده و رك بنچ (‪ )workbench‬از برنامه‌های نويسنده با عنوان ‪ ،double‬به دنبال جفتهايي از کلمات مشابه همجوار مي‌باشد‪.‬‬ ‫در اينجا يك اجرا از ‪ double‬در ‪ awk‬وجود دارد ‪:‬‬

‫‪$ cat double‬‬ ‫‪awk ′‬‬ ‫‪FILENAME ! = prevfile } # New file‬‬ ‫‪NR=1‬‬ ‫‪# vesttine number‬‬ ‫‪Prefile = FLIENAME‬‬ ‫{‬ ‫} ‪NF> 0‬‬ ‫(‪If )$( = = last word‬‬ ‫‪Printf " double %s , file %s , line %d \ n", $1, fILENAMENR‬‬ ‫(‪For )i = 2 , i < = NF, i + t‬‬ ‫((‪If ) $ I = = $ ) i –1‬‬ ‫‪Printf " double %s , file % s , line %d \ n " $I FLLENAME, NR‬‬ ‫( ‪If ) N F > 0‬‬ ‫‪Lastword = $ NF‬‬ ‫*‪{'$‬‬ ‫‪$‬‬ ‫عملگر ‪‌، + +‬عملوند خود را افزايش مي‌دهد و عملگر ‪ ،- -‬عملوند خود را کاهش مي‌دهد‪.‬‬ ‫متغیر توکار ‪ ، FILENAME‬شامل نام فايل ورودی فصلي مي‌باشد‪ .‬چون ‪‌، NR‬سطرها را از آغاز ورودی مي‌شمارد‪ ،‬در نتیجه ما آن را‬ ‫در هر زماني که اسم فايل تغییر مي‌کند‪‌،‬دوباره تنظیم مي‌کنیم‪ ،‬بنابراين‪ ،‬به اين ترتیب يك سطر مزاحم به درستي شناسايي مي‌شود ‪.‬‬ ‫بیان ‪ ، if‬دقیقا شبیه به بیان آن در ‪ C‬مي‌باشد‪:‬‬

‫(‪if )condition‬‬


‫محیط برنامه سازی لینوکس‬

‫‪113/322‬‬

‫‪statement 1‬‬ ‫‪else‬‬ ‫‪statement 2‬‬ ‫اگر ‪ condilion‬دست باشد‪ ،‬در نتیجه ‪ statement 1‬اجرا مي‌شود؛ واگر اشتباه باشد‪ ،‬و اگر بخش ‪ else‬وجود داشته باشد‪ ،‬در نتیجه‬

‫‪ statement 2‬اجرا مي‌شود‪ ،‬بخش ‪ else‬اختیاری است‪.‬‬

‫بیان ‪ ، for‬يك حلقه شبیه به حلقه موجود در ‪ C‬مي‌باشد‪ ،‬اما متفاوت از حلقة شل مي‌باشد‪:‬‬

‫(‪fo ) expressionl , condition , expression 2‬‬ ‫‪statement‬‬ ‫‪ ، for‬شبیه بیان ‪ while‬زير مي‌باشد‪‌،‬که در ‪ awk‬نیز معتبر است‪:‬‬ ‫‪expression 1‬‬ ‫} (‪while ) condition‬‬ ‫‪statement‬‬ ‫‪expression 2‬‬ ‫{‬

‫براي مثال ‪،‬‬ ‫‪)+ + for ) I = 2 , i < = NF, i‬‬ ‫حلقه را با مجموعه ‪ i‬به ترتیب ‪ ۲‬و ‪ … ۳‬تا تعداد میدانها ‪ ‌NF،‬اجرا مي‌کند‪.‬‬

‫بیان ‪ ،break‬منجر به يك خروج سريع از ‪ for‬يا ‪ while‬ضمیمه مي‌شود؛ و بیان ‪ ، continue‬منجر به تکرار بعدی برای شروع مي‌شود‬

‫همانند ‪ condition‬موجود در ‪ while‬و ‪ expression 2‬موجود در ‪ .) for‬بیان ‪ ، Next‬منجر به خوانده شدن سطر ورودی بعدی و‬

‫تطبیق طرح به منظور ايجاد خلصه در ‪‎‬آغاز برنامه ‪ awk‬مي‌شود‪ .‬بیان ‪ exit‬منجر به يك انتقال سريع به طرح ‪ END‬مي‌شود‪.‬‬ ‫جدول ‪ : ۴.۳‬متغیرهای توکار ‪awk‬‬

‫نام فايل ورودی فعلي‬

‫‪FILENAME‬‬

‫کاراکتر جداساز میدان ( پیش فرض فاصله و جدول بندی)‬

‫‪FS‬‬

‫تعداد میدانها در رکورد ورودی‬

‫‪NF‬‬

‫تعداد رکورد ورودی‬

‫‪NR‬‬

‫فرمت خروجي برای اعداد ‌(پیش فرض ‪ % g‬و به (‪ printf )۳‬مراجعه کنید‬

‫رشته جداساز میدان خروجي (پیش فرش فاصله)‬

‫رشته جداساز ثبت خروجي ( پیش فرض سطرجديد)‬

‫کاراکتر جداساز ثبت ورودی ( پیش فرض سطر جديد )‬

‫‪OFMT‬‬ ‫‪OFS‬‬ ‫‪ORS‬‬ ‫‪RS‬‬

‫جدول ‪ : ۴.۴‬علمگردهای ‪ ( awk‬به ترتیب افزايش تقدم)‬

‫تخصیص؛ ‪ V= Vop , expr = Vop‬مي‌باشد )‬

‫هر کدام باشد صحیح است ‪or : exprl || expr 2‬‬

‫‪= + = - = * = / = % = ) )expr‬‬ ‫| |‬


‫محیط برنامه سازی لینوکس‬

‫‪114/322‬‬

‫‪ expr 2‬ارزيابي نمي‌شود اگر ‪ expr‬صحیح باشد‬

‫‪ AND : expr 1 $ $ expr 2‬اگر هر دو باشند‪ ،‬صحیح است‬

‫‌‪$ $‬‬

‫‪ expr 2‬ارزيابي نمي‌شود اگر ‪ expr 1‬اشتباه باشد‬ ‫ارزش عبارت را منفي مي‌کند‬

‫ه‌اي ؛ ‪ ‬و ‪ ! ،‬‬ ‫عملگرهاي رابط ‌‬

‫!‬ ‫≈! ≈‬

‫==>>= < <‬

‫تطبیق هستند و پیوند ‌دهي رشته را تطبیق نمي‌کنند‪.‬‬

‫به اضافه ‪ ،‬منها‬

‫‪+ -‬‬

‫ضرب ‪‌،‬تقسیم ‪ ،‬باقیمانده‬

‫‪%‬‬

‫افزايش ‪ ،‬کاهش ‌(پیشوند يا پسوند )‬

‫\ *‬

‫‪+ + - -‬‬

‫آرايه‌ها‬ ‫‪ ،awk‬همانند اکثر زبانهای برنامه‌نويسي‪ ،‬آرايه‌ها را فراهم مي‌کند‪ .‬به عنوان يك مثال جزئي‪ ،‬اين برنامه ‪ ،awk‬هر سطر از ورودی را در‬ ‫يك عنصر آرايه مجزا جمع‌آوری مي‌کند و توسط شماره سطر شاخص‌بندی مي‌کند‪ ،‬سپس آنها را در يك ترکیب معکوس پرينت‬ ‫مي‌کند‪:‬‬

‫‪$ cat back words‬‬ ‫‪# backwords : print in put in backward line order‬‬ ‫{ ‪awk ′ } line ] NR[ = $o‬‬ ‫* ‪END } for ) i = NR ; i > o ; i - - ( print line ] i [′ $‬‬ ‫‪$‬‬ ‫توجه داشته باشید که همانند متغیرها ‪ ،‬آرايه‌ها نبايد اعلن شوند؛ اندازه يك آرايه فقط به حافظه موجود در ماشین شما محدود مي‌شود‪.‬‬ ‫البته‪ ،‬اگر يك فايل خیلي بزرگ در آرايه خوانده شود‪ .‬در نهايت ممکن است از حافظه خارج شود‪ .‬برای پرينت کردن انتهای يك فايل‬ ‫بزرگ در يك ترتیب معکوس‪ ،‬همکاری با ‪ tail‬لزم است ‪:‬‬

‫‪$ tail – 5 / usr / dict / web 2 | backwards‬‬ ‫‪zymurgy‬‬ ‫‪zumotically‬‬ ‫‪zymotic‬‬ ‫‪zymothenic‬‬ ‫‪zymosis‬‬ ‫‪$‬‬

‫‪ ،tail‬از مزيت يك عملکرد از سیستم فايل با عنوان ‪ ، seeking‬برای پیشرفت به سمت پايان يك فايل بدون خواندن داده‌های مزاحم‬

‫استفاده مي‌کند‪ .‬به بحث و بررسي ‪ seek 1‬در فصل ‪ ۷‬مراجعه کنید‪ ( .‬نسخه محلي ما از ‪ tail‬دارای يك انتخاب ‪ -r‬مي‌باشد که سطرها‬ ‫را در يك ترتیب معکوس پرينت مي‌کند‪ ،‬به طوريکه عقب رها را جايگزين مي‌کند)‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪115/322‬‬

‫پردازش ورودی عادی‪ ،‬هر سطر ورودی را در میدانها تقسیم مي‌کند‪ .‬اين امکان وجود دارد که همین عملکرد تقسیم میدان را روی‬ ‫هررشته‌ای با عملکرد توکار ‪ Split‬انجام دهیم‪:‬‬

‫(‪n=split)s,arr,sep‬‬ ‫رشتة ‪ n‬را درون میرانهايي تقسیم مي‌کند که در عناصر ‪ 1‬تا ‪ n‬از آراية ‪ arr‬ترتیب‌بندی مي‌شوند‪ .‬اگر يك کاراکتر جداساز ‪ sep‬فراهم‬

‫شود‪ ،‬استفاده مي‌شود ؛ در غیر اين صورت ارزش جاری ‪ Fs‬استفاده مي‌شود‪ .‬برای مثال‪ " : "‌( ،‬و ‪ a 0$ ,( split‬سطر ورودی را بر‬

‫روی «دو نقطه‌ها» تقسیم مي‌کند که برای پرداش ‪ / etc/passwd‬مناسب مي‌باشد و ( " ‪ " /‬و ‪ date‬و " ‪ ، split )" 9/29/ 83‬يك ‪date‬‬ ‫را بر روی اسلش‌ها‪ ،‬تقسیم مي‌کند‪.‬‬

‫‪$ sed 1q/etc / passwd: awk' ]split)$o,a, ":",print a ]1[ [' root‬‬ ‫'[[‪$ echo 9/29/83 : awk ' ]split)$o,date," / " ( , print date ]3‬‬ ‫‪83‬‬ ‫‪$‬‬ ‫جدول ‪ ،۴.۵‬عملکردهای توکار ‪ awk‬را فهرست‌بندی مي‌کند‪.‬‬ ‫جدول ‪ : ۴.۵‬عملکردهای توکار ‪awk‬‬ ‫کسینوس ‪expr‬‬

‫‪)cos)expr‬‬

‫تابع نمايي ‪expr: eexpr‬‬

‫‪) exp )pxpr‬‬

‫سطر ورودی بعدی را مي‌خواند ‪ :‬صفر را برمي‌گرداند اگر پايان فايل باشد‬ ‫اگر پايان فايل نباشد‪ 1 ،‬را بر مي‌گرداند‬

‫موقعیت رشته ‪ S2‬در ‪ :s1‬اگر آشکار نشود صفر را بر مي‌گرداند‬ ‫مي‌کند‬

‫‪) ( get line‬‬

‫‪ )index)s1,s2‬بخش صحیح ‪ expr‬؛ به طرف صفر سر راست‬

‫‪)int)expr‬‬

‫طول رشته ‪s‬‬

‫‪)length )s‬‬

‫لگاريتم طبیعي ‪expr‬‬

‫‪)log )expr‬‬

‫سینوس ‪expr‬‬

‫‪)sin )expr‬‬

‫تقسیم ‪ s‬بر ] [‪ ]n a … ]1‬روی کاراکتر ‪ c‬؛ (‪ s‌ ,a,c( split n‬را بر مي‌گرداند ‪.‬‬ ‫فرمت … بر طبق ويژگي ‪fmt‬‬

‫‪sprint f)fmt‬‬

‫‪)…,‬‬

‫آرايه‌هاي انجمني‬ ‫يك مشکل استاندارد در پردازش داده‌ها‪ ،‬جمع‌آوری ارزشها برای يك مجموعه از جفت‌های نام ‪ /‬ارزش مي‌باشد‪ .‬چنین چیزی از‬ ‫ورودی به صورت زير است‪.‬‬

‫‪400‬‬ ‫‪100‬‬ ‫‪200‬‬ ‫‪300‬‬ ‫‪100‬‬ ‫‪100‬‬ ‫‪100‬‬

‫‪susie‬‬ ‫‪John‬‬ ‫‪Mary‬‬ ‫‪Mary‬‬ ‫‪John‬‬ ‫‪Susie‬‬ ‫‪Mary‬‬


‫محیط برنامه سازی لینوکس‬

‫‪116/322‬‬

‫ما مي‌خواهیم ارزش کل را برای هر نام محاسبه کنیم‪:‬‬

‫‪John‬‬ ‫‪200‬‬ ‫‪Mary‬‬ ‫‪600‬‬ ‫‪Susie‬‬ ‫‪500‬‬ ‫‪ ، awk‬يك روش موثر را برای انجام اين کار فراهم مي‌کند‪ ،‬آرايه انجمني‪ .‬اگر چه فرد در حالت عادی زيرنويسهای آرايه را به عنوان‬ ‫اعداد صحیح تصور مي‌کند‪ ،‬اما در ‪ awk‬هر ارزش مي‌تواند به عنوان يك زيرنويس استفاده مي‌شود‪ .‬بنابراين‬

‫[‪]sum]$1[+=$2‬‬ ‫‪}for )name in sum( print name , sum ]name‬‬

‫‪}]END‬‬

‫يك برنامه کامل برای جمع کردن و چاپ کردن مجموع جفت‌های نام ‪ -‬ارزش همانند موارد مذکور در بال مي‌باشد‪ ،‬حال چه آنها‬

‫ترتیب بندی شوند و چه نشوند‪.‬‬

‫هر نام (‪ )$1‬به عنوان يك زيرنويس در مجموع استفاده مي‌شود؛ در پايان‪ ،‬يك شکل خاص از بیان ‪ ، for‬برای تکرار شدن در تمام‬

‫عناصر مجموع به کار مي‌رود و آنها را پرينت مي‌کند‪ .‬از نظر نحوی‪ ،‬اين متغییر از بیان ‪ ، for‬به اين صورت مي‌باشد‬ ‫اگرچه‪،‬‬

‫(‪For )var in array‬‬ ‫‪statement‬‬ ‫همانند حلقة ‪ for‬در شل به نظر مي رسد‪ ،‬اما نامربوط مي‌باشد‪ .‬بیان ‪ for‬بر روی زيرنويس‌های آرايه و نه بر روی‬

‫عناصر‪ ،‬حلقه‌سازی مي‌کند و ‪ ‌Var‬را برای هر زيرنويس به ترتیب معین مي‌کند‪ .‬زيرنويسها‪ ،‬در يك ترتیب غیرقابل پیش‌بیني بوجود‬ ‫مي‌آيند‪ ،‬بنابراين ترتیب بندی آنها لزم است‪.‬‬

‫در مثال بال‪ ،‬خروجي مي‌تواند درون ‪ Sort‬برای فهرست کردن افراد با بزرگترين ارزشها در بال‪ ،‬لوله‌گذاری شود‪.‬‬

‫‪$ awk ' …' | sort + lny‬‬ ‫تحقق حافظه انجمني‪ ،‬از يك برنامه هش‌زني استفاده مي‌کند برای اينکه اطمینان دهد که به هر عنصری با میزان زمان يکسان با عنصری‬ ‫ديگر‪ ،‬دستیابي مي‌کند و اينکه ( حداقل برای اندازه‌های متوسط آرايه) زمان به تعداد عناصر موجود در آرايه‪ ،‬بستگي ندارد‪.‬‬

‫حافظه انجمني برای وظايفي مانند شمارش همه کلمات در ورودی مؤثر است‪:‬‬

‫‪$ cat word freg‬‬ ‫{‪awk' }for )I=1,i <=NF, I+t(num]$I[++‬‬ ‫{[‪END }for )word in num(print word , num]word‬‬ ‫*‪' $‬‬ ‫‪$ word freg ch40* | sort +1 -nr | sed 20q | 4‬‬ ‫‪the 372‬‬ ‫‪.cw 345‬‬ ‫‪of 22‬‬ ‫‪is 185‬‬ ‫‪to 175‬‬ ‫‪a 167‬‬ ‫‪in 109‬‬ ‫‪and 100‬‬ ‫‪.p1 94‬‬ ‫‪.p2 94‬‬ ‫‪pp9‬‬ ‫‪$87‬‬ ‫‪awk87‬‬ ‫‪sed 83‬‬ ‫‪tha 76 for 75‬‬ ‫‪The 63‬‬ ‫‪are 61‬‬ ‫‪line 55‬‬ ‫‪print 52‬‬ ‫‪$‬‬ ‫اولین حلقه ‪ ، for‬به هر کفه در سطر ورودی نگاه مي‌کند و عنصر آرايه زيرنويس شده ‪ num‬را توسط کلمه‪ ،‬افزايش مي‌دهد (‪ i$‬از‬

‫‪ awk‬میدن ‪ i‬از سطر ورودی را با هر کدام از متغیرهای شل اشتباه نگیريد)‪ .‬پس از اينکه فايل خوانده شد‪ ،‬دومین حلقه ‪ ، for‬در يك‬

‫ترتیب اختیاری‪ ،‬کلمات و شماره‌های آنها را پرينت مي‌کند‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪117/322‬‬

‫تمرين ‪ ،۴.۹‬خروجي از ‪ word freg‬شامل فرمانهای فرمت کننده متن مانند ‪ cw‬مي‌باشد که برای پرينت کلمات در اين فونت استفاده‬ ‫مي شود‪ .‬چگونه شما از مواردی که کلمه نمي‌باشند خلص مي‌شويد؟ چگونه شما از ‪ tr‬برای انجام کار ‪ wordfreg‬به طور صحیح‬

‫بدون توجه به مورد ورودی آن‪ ،‬استفاده مي‌کنید؟ تحقق و عملکرد ‪ word freg‬را با خط لوله‌ای از بخش ‪ ۴.۲‬و با اين مورد مقايسه‬ ‫کنید‪:‬‬

‫*[→] [→] ‪Sed' s /‬‬ ‫‪/g'$*:fort | uniq –c | sort - nr‬‬

‫رشته‌ها‬ ‫اگر چه ‪ sed‬و ‪ awk‬هر دو برای کارهای جزئي مانند انتخاب يك میدان تنها استفاده مي‌شوند‪ ،‬اما ‪ awk‬فقط برای وظايفي که حقیقتاً‬ ‫نیاز به برنامه‌نويسي دارند‪ ،‬استفاده مي‌شود وتا هر میزاني قابل استفاده است‪ .‬يك مثال در اين خصوص‪ ،‬برنامه‌ای است که سطرهای‬

‫طولني را تا ‪ ۸۰‬ستون تا مي‌کند ‪ .‬هر سطری که بیش از ‪ ۸۰‬کاراکتر داشته باشد پس از کاراکتر ‪ ،۸۰‬شکسته مي‌شود؛ يك \ به عنوان‬ ‫يك اخطار ضمیمه مي‌شود و مابقي آن ادامه مي‌ يابد‪ .‬بخش نهايي يك سطر تا شده‪ ،‬هم ستون شده از راست مي‌باشد نه هم از ستون‬

‫شده از چپ‪ ،‬چون هم ستون شده از راست خروجي مناسب‌تری را برای صورتهای برنامه تهیه مي‌کند‪ ،‬که اين چیزی است که ما اغلب‬ ‫از ‪ fold for‬استفاده مي‌کنیم‪ .‬به عنوان يك مثال‪ ،‬از سطرهای ‪ ۲۰‬کاراکتری بجای ‪ ۸۰‬کاراکتری استفاده مي‌کنیم و‬

‫‪$ cat test‬‬ ‫‪A short lihe‬‬ ‫‪A somewhat longer line‬‬ ‫‪This line is quilte a bit/ onger than the last one.‬‬ ‫‪$ fold test‬‬ ‫‪A short line‬‬ ‫\‪A somewat linger li‬‬ ‫‪ne.‬‬ ‫\‪This line is quite a‬‬ ‫\‪Bit linger than the‬‬ ‫‪Last one.‬‬ ‫‪$‬‬ ‫عجیب است که هفتمین ويرايش‪ ،‬برنامه‌ای را برای افزودن يا کم کردن جدول ‌بندی‌ها‪ ،‬فراهم نمي‌کند‪ ،‬اگر ‪ pr‬در سیستم ‪ ، v‬هر دو را‬

‫انجام مي‌دهد‪ .‬اجرای ما ا ز ‪ ، fold‬از ‪ ‌sed‬برای تبديل جدول بندی ها به فاصله ها استفاده مي کند‪ ،‬در نتیجه شمار کاراکتر ‪، awk‬‬

‫صحیح مي‌باشد‪ ،‬چنین چیزی به طور صحیح برای جدول‌بندی‌های اصلي کار مي‌کند ( دوباره‪ ،‬نمونه مبدأ برنامه) اما ستونها را برای‬ ‫جدول بندی‌ها در وسط سطر‪ ،‬حفظ نمي‌کند‪.‬‬

‫‪# fold: fold long lines‬‬ ‫‪sed ' /→/‬‬ ‫[‪/g' $*| # converttabsto 8 spaces‬‬ ‫'‪awk‬‬ ‫}‪BEGIN‬‬ ‫‪N=80‬‬ ‫‪#folds at column 80‬‬ ‫‪For )I=1, <=N,I+t( # make astring of blanks‬‬


‫محیط برنامه سازی لینوکس‬

‫‪118/322‬‬

‫" " ‪Blanks = blanks‬‬ ‫{‬ ‫}‬ ‫(‪if )n = lingth )$o( <=n‬‬ ‫‪print‬‬ ‫}‪else‬‬ ‫{(‪for ) I=1, n>N,n-=N‬‬

‫(‪printf " % s \\\n" , substr)$o, i,N‬‬

‫‪i t=N,‬‬ ‫{‬ ‫(‪printf " s%s \n", substr )blanks , 1 ,N –n(, substr)$O,i‬‬ ‫{‬ ‫'{‬ ‫در ‪ awk‬عملگر پیوند دهي رشته به صورت آشکار وجود ندارد؛ رشته‌ها به هم محلق مي‌شوند‪ ،‬زماني که آنها هم جوار هستند‪ .‬در ابتدا‪،‬‬

‫‪ blanks‬يك رشته تهي مي‌باشد‪ .‬حلقه در بخش ‪ ، BEGIN‬يك رشته بلند از ‪ blank‬ها را ازطريق پیوند دهي بوجود مي‌آورد‪:‬‬

‫هر حرکت در اطراف حلقه‪ ،‬يك ‪ blank‬ديگر به انتهای ‪ blank‬ها اضافه مي‌کند‪ .‬دومین حلقه سطر ورودی را در ‪ chunk‬ها پردازش‬ ‫مي‌کند تا جايي که بخش باقیمانده به میزان کافي کوتاه مي‌باشد ‪ .‬همانند ‪ ، C‬بیان تخصیص مي‌تواند به عنوان يك عبارت استفاده شود‪،‬‬ ‫بنابراين ساخت‬

‫…(‪If ))n = 1ength)$o(( <=N‬‬ ‫طول سطر ورودی به ‪ n‬اختصاص مي‌دهد قبل از اينکه ارزش را آزمايش کند‪ ،‬به پرانتزها توجه داشته باشید‪.‬‬

‫تمرين ‪ fold ، ۴.۱۰‬را به گونه‌ای تغییر دهید که سطرها را در فاصله ‌ها يا جدول‌بندی ها تا کند به جای اينکه کلمه را تقسیم کند ‪ .‬آن را‬

‫برای کلمات طولني‌تر‪ ،‬به طور مطلوب بسازيد‪.‬‬

‫برهم كنش با شل‬ ‫فرض کنید شما مي خواهید يك برنامة ‪ fieldn‬را به گونه‌ای بنويسید که میدان ‪ n‬ام از هر سطر ورودی را پرينت کند‪‌ ،‬بنابراين شما‬ ‫برای مثال مي‌گوئید‪،‬‬

‫‪who | field $‬‬ ‫برای اينکه فقط اسامي ‪ login‬را پرينت کنید ‪ awk .‬به وضوح‪ ،‬توانايي انتخاب میدان را فراهم مي‌کند ؛ مشکل عمده عبور تعداد ‪n‬‬ ‫میدان در يك برنامه‌ ‪ awk‬مي‌باشد‪ .‬در اينجا يك تحقق وجود دارد‪:‬‬

‫' { '‪awk' }print $' $1‬‬ ‫‪ ،$1‬عرضه مي‌شود ( درون نقل قولها نمي‌باشد) و بنابراين عدد میداني مي‌شود که توسط ‪ awk‬مشاهده مي‌شود‪ .‬روش ديگر‪ ،‬استفاده از‬ ‫نقل قولهای دوگانه مي‌باشد‪:‬‬

‫" { ‪awk " }print 1 $ $ 1‬‬ ‫در اين مورد‪ ،‬آرگومان‪ ،‬توسط شل تفسیر مي‌ شود‪ ،‬بنابراين‪ 1$ ،‬به ‪ $‬تبديل مي‌شود و ‪ ،$1‬توسط ارزش ‪ n‬جايگزين مي‌شود‪ .‬ما روش‬

‫نقل قول منفرد را ترجیح مي دهیم چون بسیاری از ‪ s,1‬اضافي با روش نقل قول دوگانه در يك برنامه نوعي ‪ awk‬لزم هستند‪.‬‬ ‫دومین مثال‪ addup n ،‬مي‌باشد که شماره‌ها رابه ‪ n‬امین میدان اضافه مي‌کند‪:‬‬


‫محیط برنامه سازی لینوکس‬

‫سومین مثال‪ ،‬مجموع‌های مجزايي را از هر کدام از ستونهای ‪ -n‬همراه با مجموع کل تشکیل مي‌دهد‪:‬‬

‫‪119/322‬‬

‫{'‪awk' } s += $' $ 1‬‬ ‫'{‪END }print s‬‬

‫'‪awk‬‬ ‫{'‪BEGIN}n = ' $ 1‬‬ ‫}‬ ‫(‪for )i=1 ,i <n, I+t‬‬ ‫‪sum ]i[ t = $I‬‬ ‫{‬ ‫} ‪END‬‬ ‫}(‪for )i=1 , i <=n, , i+t‬‬ ‫[‪Printf " % 4g " , sum]i‬‬ ‫{‬ ‫‪printf " , total = % 4g \ n " , total‬‬ ‫'{‬ ‫ما از ‪ BEGIN‬برای درج ارزش ‪ n‬در يك متغیر استفاده مي‌کنیم‪ ،‬به جای اينکه مابقي برنامه را با نقل قولها دسته‌بندی کنیم‪.‬‬ ‫مشکل عمده با همه اين مثالها‪ ،‬نگهداشتن رد چیزی نیست که در داخل يا خارج از اين نقل قولها مي‌باشد( اگر چه‪ ،‬يك دردسراست)‪،‬‬ ‫بلکه همانگونه که اخیر ًا نوشته شده است‪ ،‬اين برنامه‌ها مي‌توانند فقط وردی استاندارد خود را بخوانند ؛ راهي برای عبور آنها‪ ،‬هم پارامتر‬

‫‪ n‬و هم يك فهرست باند اختیاری از اسامي فايلها وجود ندارد چنین چیزی نیازمند برنامه‌نويسي شل مي‌باشد که ما در فصل بعد به آن‬ ‫مي‌پردازيم‪.‬‬

‫يك سرويس تقويم بر اساس ‪awk‬‬ ‫مثال اخیر ما از آرايه‌های انجمني استفاده مي‌کند ؛ همچنین يك شرح از چگونگي بر هم کنش با شل وجود دارد و تا حدودی در مورد‬

‫ارزيابي برنامه‪ ،‬شرح مي‌دهد‪.‬‬

‫وظیفه‪ ،‬اين است که سیستم هر روز صبح پستي را برای شما بفرستد که شامل يك تقويم از وقايع آينده باشد‪ .‬ممکن است چنین‬

‫سرويس تقديمي وجود داشته باشد ؛ به ‪ )calender )1‬مراجعه کنید‪ .‬اين بخش يك روش ديگر را نشان مي‌دهد)‪.‬‬

‫سرويس اصلي بايد به شما وقايعي را بگويد که امروز اتفاق مي‌افتد ؛ دومین مرحله‪ ،‬دادن يك هشدار روزانه مي‌باشد ‪ -‬وقايع فردا‬

‫همانند وقايع امروز‪ ،‬استفاده صحیح از پايان هفته‌ها و تعطیلت به عنوان يك تمرين باقي مي‌ماند‪.‬‬

‫اولین شرط لزم مکاني است که تقويم را نگه دارد‪ .‬برای چنین کاری يك فايل با عنوان ‪ ، calender in/ usr / you‬آسانترين راه‬ ‫مي‌باشد‪.‬‬

‫‪$ cat calender‬‬ ‫‪sep 30 mother’s birthday‬‬ ‫‪oct 1 1unch with joe.noon‬‬ ‫‪oct 1 metting 4 pm‬‬ ‫‪$‬‬ ‫دوم‪ ،‬شما نیاز به يك روش برای پويش کردن تقويم برای يك تاريخ داريد‪ .‬در اينجا انتخابهای زيادی وجود دارند؛ ما از ‪ awk‬استفاده‬

‫مي‌کنیم چون در انجام محاسبات لزم برای رفتن از امروز به فردا‪‌ ،‬بهترين مي‌باشد‪ ،‬اما شايد برنامه‌ها مانند ‪ sed‬يا ‪ egrep‬نیز مي‌توانند‬ ‫موثر باشند‪ .‬سطرهای انتخاب شده از تقويم‪ ،‬توسط پست الکترونیکي ‪ ،‬ارائه مي‌شوند‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪120/322‬‬

‫سوم اينکه‪ ،‬شما نیاز به يك روش برای داشتن تقويم پويش شده به صورت قابل اعتماد و خودکار در هر روز و احتمال ً در صبح‪،‬‬ ‫داريد‪ .‬چنین چیزی مي‌تواند با ‪ at‬انجام شود‪ ،‬چیزی که ما به طور خلصه در فصل اول ذکر کرديم ‪.‬‬

‫اگر ما فرصت تقويم را محدود کنیم در نتیجه هر سطر با يك نام ماه و روز به عنوان تاريخ آغاز مي‌شود‪ ،‬اولین نمونه برنامه تقويم آسان‬

‫است‪:‬‬

‫‪$ date‬‬ ‫‪Thu sep 29 15:23 : 12 EDT 1983‬‬ ‫‪$ cat bin / calender‬‬ ‫‪# calendar:Version 1 - - today only‬‬ ‫‪awk < $ HOME / calendar‬‬ ‫{(‪BEGIN } split )" " \ date \ " " , date‬‬ ‫[‪$ 1= = date ]2[ $ $ $2 = = date ]3‬‬ ‫‪| mail $NAME‬‬ ‫‪$‬‬ ‫بلوك ‪ ، BEGIN‬تاريخ ايجاد شده توسط ‪ date‬را در يك آرايه تقسیم مي‌کند؛ دومین و سومین عنصر آرايه‪ ،‬ماه و روز مي‌باشند‪ .‬ما‬

‫فرض مي‌کنیم که متغیر ‪ Name‬از شل‪ ،‬شامل اسم ‪ ‌login‬شما مي‌باشد‪.‬‬

‫توالي قابل توجه کاراکترهای نقل قول‪ ،‬نیازمند داشتن تاريخ در يك رشته در وسط برنامه ‪ awk‬مي‌باشند‪ .‬يك روش ديگر که آسانتر‬ ‫مي‌باشد اين است که تاريخ را به عنوان اولین سطر ورودی بپذيريم‪:‬‬

‫‪$ cat bin / calendar‬‬ ‫‪# celendar : version 2 - - today only .no quotes‬‬ ‫| (‪)date , cat sHOME / calendar‬‬ ‫' ‪awk‬‬ ‫‪NR = = 1 }mon = #2 , day = $3{# set the date‬‬ ‫‪NR > 1 $ $ $1= = mon $ $ $ 2 = = day # print calendar lines‬‬ ‫‪| mail $ NAME‬‬ ‫مرحله بعدی‪ ،‬مرتب کردن تقويم برای ديدن وقايع فردا همانند امروز مي‌باشد‪ .‬اکثر اوقات‪ ،‬همه آن چیزی که مورد نیاز است‪ ،‬گرفتن‬

‫تاريخ امروز و اضافه کردن ‪ ۱‬به روز است‪ .‬اما در پايان ماه‪ ،‬ما بايد ماه بعد را وارد کنیم و روز را دوباره به يك برگردانیم‪ .‬و البته هر‬ ‫ماه دارای يك تعداد متفاوت از روزها مي‌باشد‪.‬‬

‫اينجا جايي است که آرايه انجمني سودمند مي‌باشد‪ .‬دوآرايه‪ ،Nextman ,days ،‬که زيرنويس‌های آنها اسامي ماه هستند‪ ،‬تعداد روزها‬

‫در يك ماه و نام ماه بعدی را با خود دارند‪ .‬بنابراين ‪ days]" Jan" [ . 31‬و [" ‪( Jan"[ Feb,next mon‬فوريه) مي‌باشد‪ .‬به جای ايجاد‬

‫يك توالي کامل از بیاناتي مانند‬

‫"‪dsys ]" Jan"[ = 31 , next mon ]"Jan"[ = " Feb‬‬ ‫"‪days ]" Feb" = 28 , nextmon ]" Feb"[ = " mar‬‬ ‫ما از ‪ split‬برای تبديل يك ساختار مناسب از داده‌ها به يك ساختار حقیقت ًا مورد نیاز استفاده مي‌کنیم‪:‬‬ ‫‪$ cat calendar‬‬ ‫‪# calendar: version 3 - - today and tomorroew‬‬ ‫‪awk <$ HOME / calendar‬‬ ‫} ‪BEGIN‬‬ ‫" ‪x = " Jan 31 Feb 28 Mar 31 Apr 30 may 31‬‬ ‫"‪" Jan 31 Aug 31 sep30 oct31 nov30 Dec31 Jan 31‬‬ ‫(‪split )x , data‬‬


‫محیط برنامه سازی لینوکس‬

‫‪121/322‬‬

‫{(‪for )i=1 , I )24 , I t=2‬‬ ‫[‪days ]data]i[ [=data]i+1‬‬ ‫[‪next mon ]dafa]i[[=data]I+2‬‬ ‫{‬ ‫(‪split )" , " \ date ‘ " , " , date‬‬ ‫[‪mon / = date ]2[ , day / = date ]3‬‬ ‫‪mon2= mon/, day 2 = day 1+1‬‬ ‫{( [‪if)day( > = days ]mon1‬‬ ‫‪day 2 =1‬‬ ‫[‪mon 2=next mon ] mon1‬‬ ‫{‬ ‫‪$ 1 = = mon 1 $ $ $2 = = day || $1 = = mon 2 $ $ $2 = = day 2‬‬ ‫‪| mail $ NAME‬‬ ‫‪$‬‬ ‫توجه داشته باشید که ‪ Jan‬در يك داده دوباره ظاهر مي‌شود ؛ يك ارزش داده« اشاره نما » مانند اين‪ ،‬پردازش را برای دسامبر آسان‬ ‫مي‌کند‪.‬‬

‫مرحله نهايي‪‌ ،‬مرتب کردن برنامه تقويم به گونه‌ای مي‌باشد که هر روز اجرا شود‪ .‬چیزی که شما مي‌خواهید اين است که هر روز صبح‬

‫حدود ساعت ‪ ۵‬صبح از خواب بیدار شويد و ‪ calendar‬را اجرا کنید‪ .‬شما مي‌توانید اين کار را با به خاطر آوردن برای ‪ say‬خودتان‬

‫انجام دهید ( هر روز !)‬

‫‪$ at 5am‬‬ ‫‪calendar‬‬ ‫‪ct1-d‬‬ ‫‪$‬‬ ‫اما چنین چیزی دقیقاًـ قابل اعتماد يا خودکار نمي‌باشد‪ .‬ترفند اين است کهـ ‪ at‬رانه فقط برای اجرای تقويم‪ ،‬بلکه همچنین برای‬ ‫برنامه‌ريزی اجرای بعدی نیز بیان کنیم‪.‬‬

‫‪$ cat early .morning‬‬ ‫‪calendar‬‬ ‫‪echo early . morning | at 5 am‬‬ ‫‪$‬‬ ‫دومین سطر‪ ،‬فرمان ‪ at‬ديگری را برای روز بعد‪ ،‬برنامه‌ريزی مي‌کند‪ ،‬در نتیجه زماني که شروع مي‌شود‪ ،‬اين توالي‪ ،‬به صورت دائمي‬

‫مي باشد‪ .‬فرمان ‪ ، at PATH‬شما را و نیز فهرست جاری و ساير پارامترها را برای فرمانهايي که پردازش مي‌کند‪ ،‬تعیین مي‌کند‪،‬‬ ‫بنابراين شما نبايد کار خاصي انجام دهید‪.‬‬

‫تمرين ‪ . ۴-۱۱‬تقويم را به گونه‌ای تغییر دهید که در خصوص آخر هفته‌ها نیز بداند‪ .‬در جمعه‪« ،‬فردا» شامل شنبه‪ ،‬يکشنبه و دوشنبه‬

‫مي‌باشد‪ .‬تقويم را به گونه‌ای تغییر دهید که به صورت پرشي از سال استفاده کند‪ .‬آيا تقويم در خصوص تعطیلتها بايد چیزی مي‌داند؟‬

‫چگونه آن را مرتب مي‌کنید؟‬

‫تمرين ‪ . ۴-۱۲‬آيا تقويم در خصوص تاريخهای موجود در يك سطر بايد بداند‪ ،‬نه فقط در آغاز سطر؟ در خصوص تاريخهای ارائه‬

‫شده در ساير فرمتها مانند ‪ ۱۰/۱/۸۳‬چطور؟‬

‫تمرين‪ .۴-۱۳‬چرا تقويم به جای ‪ $NAME‬از ‪ getname‬استفاده نمي‌کند؟‬


‫محیط برنامه سازی لینوکس‬

‫‪122/322‬‬

‫تمرين ‪ . ۴-۱۴‬يك نسخه شخصي از ‪ rm‬بنويسید که فايلها را وارد يك فهرست موقتي کند به جای اينکه آنها را حذف کند‪ ،‬اين کار را‬ ‫با يك فرمان ‪ at‬برای پاك کردن فهرست انجام دهید زماني که شما خواب هستید‪.‬‬

‫پايان‌هاي آزاد‬ ‫‪ awk‬يك زبان بد ترکیب مي‌باشد‪ ،‬ـ و نشان دادن همة توانايي‌های آن در يك فصل با اندازه معقول‪‌ ،‬غیرممکن مي باشد‪ .‬در اينجا‬ ‫چیزهای ديگری وجود دارند که در کتاب راهنما به آنها مي‌پردازيم‪:‬‬

‫‪۰‬جهت دهي خروجي ‪ print‬در فايلها و لوله‌ها‪ :‬هر بیان ‪ print‬يا ‪ ، printf‬مي‌تواند با يك > و يك اسم فايل دنبال شود ( به عنوان يك‬

‫رشته نقل قول شده يا در يك متغیر) ؛ خروجي به همان فايل فرستاده مي‌شود‪ .‬همانند شل « << » به جای روی هم نويسي‪‌ ،‬ضمیمه‬ ‫مي‌شود‪ .‬پرينت کردن درون يك لوله به جای > نیاز به | دارد‪.‬‬

‫‪۰‬رکوردهای چند سطری‪ :‬اگر جداساز ‪ Rs‬رکورد‪ ،‬برای سطر جديد تعیین شود‪ ،‬درنتیجه رکوردهای ورودی توسط يك سطر خالي از‬ ‫هم جدا مي‌شوند‪ .‬در اين روش‪ ،‬سطرهای ورودی متعددی مي‌توانند به عنوان يك رکورد منفرد رفتار کنند‪.‬‬

‫«‪۰‬طرح ‪ ،‬طرح» به عنوان يك گزينش‌گر‪:‬همانند ‪ sed , ed‬يك دامنه از سطرها مي‌توانند توسط يك جفت طرح مشخص شوند ‪ .‬چنین‬ ‫چیزی سطرها را از يك رخداد از اولین طرح تا رخداد بعدی دومین طرح‪ ،‬تطبیق مي‌دهد‪ .‬يك مثال ساده عبارت است از‬ ‫که سطرهای ‪ ۱۰‬تا ‪ ۲۰‬شامل را تطبیق مي‌کند‪.‬‬

‫‪NR = = 10 , NR = = 20‬‬

‫‪ ۴.۵ ‬فايلها و فيلترهاي خوب‬ ‫اگر چه مثالهای اخیر درمورد ‪ ،awk‬فرمانهای خود شامل هستند‪ ،‬اما اکثر استفاده‌های ‪ ، awk‬برنامه‌های ساده يك سطری يا دو سطری‬

‫برای انجام پای يیدن به عنوان بخشي از يك خط لوله بزرگتر مي باشند‪ .‬چنین چیزی در مورد اکثر فیلترها صحیح مي‌باشد‪ -‬گاهي‬

‫اوقات مشکل موجود مي‌تواند با به کار بردن يك فیلتر تنها حل شود‪ .‬اما عموماًـ ‪ ،‬اين مشکل به مشکلت فرعي قابل حل توسط‬

‫فیلترهای متصل شده به هم در يك خط لوله‌‪ ،‬تجزيه مي‌شود‪ .‬اين استفاده از ابزار اغلب به عنوان قلب محیط برنامه‌نويسي يونیکس ذکر‬ ‫مي‌شود‪ .‬اين نظريه‪ ،‬کامل محدود کننده مي‌باشد؛ با اين وجود‪ ،‬استفاده از فیلترها‪ ،‬سیستم را گسترش مي‌دهد و مشاهده چگونگي‬

‫عملکرد آن‪ ،‬ارزشمند است‪.‬‬

‫خروجي تهیه شده توسط برنامه‌های يونیکس‪ ،‬ـ در يك فرمت مي‌باشد و به عنوان ورودی توسط ساير برنامه ها قابل درك است‪.‬‬

‫فايلهای قابل فیلتر‪ ،‬شامل سطرهايي از متن‪ ،‬فاقد عنوانهای تزئیني ‪ ،‬دنباله‌ روها يا سطرهای فاصله مي‌باشند‪ .‬هر سطر يك هدف از‬ ‫منفعت مي باشد ‪ -‬يك اسم فايل‪ ،‬يك کلمه‪ ،‬يك توصیف از يك فرآيند اجرا ‪ -‬بنابراين برنامه‌هايي مانند ‪ wc‬و ‪ grep‬مي‌توانند اقلم‬

‫جالب را بشمارند و يا از طريق نام در جستجوی آنها باشند‪ .‬زماني که اطلعات بیشتری برای هر هدف ارائه مي‌شود‪ ،‬فايل هنوز سطر به‬

‫سطر است‪ ،‬اما درون زمینه‌های جدا شده توسط فاصله‌ها يا جدول‌بندی‌ها ستون بندی مي‌شود‪ ،‬مانند خروجي ‪ .ls-1‬با توجه به داده‌های‬

‫تقسیم شده به چنین زمینه‌هايي‪ ‌ ،‬برنامه‌هايي مانند ‪ awk‬مي‌توانند به آساني انتخاب شوند‪ ،‬توسعه يابند و يا دوباره اطلعات را مرتب‬ ‫کنند‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪123/322‬‬

‫فیلترها‪‌ ،‬دارای يك طرح مشترك مي‌باشند‪ .‬هر کدام از آنها بر روی خروجي استاندارد خود‪ ،‬نتیجه پردازش فايلهای آرگومان را‬

‫مي‌نويسد و يا بر روی ورودی استاندارد‪ ،‬اگر هیچ آرگوماني ارائه نشود‪ ،‬آرگومان‌ها فقط ورودی‌ها را مشخص مي‌کنند و هرگز خروجي‬

‫را مشخص نمي‌کنند‪ ،‬ـ در نتیجه خروجي يك فرمان مي‌تواند همیشه درون يك خط لوله‌ای پیش برود‪ .‬آرگومانهای انتخابيـ ( يا‬

‫آرگومان‌هايي که اسم فايل نمي‌باشد مانند طرح ‪ ، )grep‬قبل از اسامي فايلها قرار مي‌گیرند‪ .‬در آخر‪ ،‬پیغامهای اشتباه بر روی خطای‬

‫استاندارد نوشته مي‌شوند‪ ،‬بنابراين‪ ،‬آنها درون يك لوله ناپديد نمي‌شوند‪.‬‬

‫اين تبديل‌ها‪ ،‬دارای اثرات اندکي بر روی فرمانهای فردی مي‌باشند‪ ،‬اما زماني که به طور يکنواخت برای همه برنامه‌ها بکار مي‌روند‪،‬‬ ‫منجر به يك سهولت در امر ارتباط مي‌شوند‪ ،‬چیزی که توسط مثالهای زيادی در سراسر اين کتاب شرح داده مي‌شود‪ ،‬اما شايد به‬

‫طورچشمگیری‪ ،‬توسط مثال شمارش کلمه در پايان بخش ‪ ۴.۲‬شرح داده شوند‪ .‬اگر همة برنامه‌ها خواهان يك ورودی نامگذاری شده يا‬ ‫فايل خروجي باشند‪ ،‬برای تشخیص پارامترها نیازمند ارتباط باشند ‪ ،‬و يا عنوان‌ها و دنباله روها را بوجود آورند‪ ،‬خط لوله‌ای کار نمي‌کند‬

‫ و البته‪ ،‬اگر سیستم يونیکس لوله‌ها را تهیه نکرده باشد‪ ،‬فرد بايد يك برنامه تبديلي برای انجام اين کار بنويسید‪ .‬اما لوله‌ها وجود دارند‬‫و خط لوله‌‌ای کار مي‌کند و حتي نوشتن آسان است اگر شما با ابزارها آشنا باشید‪.‬‬

‫تمرين ‪ ، ps . ۴.۱۵‬يك عنوان توضیحي را پرينت مي‌کند و ‪ ls-1‬تعداد کل بلوکها را در فايلها اعلن مي‌کند‪ .‬شرح دهید‪.‬‬

‫تاريخچه و نكات كتاب‌شناسي‬ ‫يك بررسي خوب ازطرح تطبیق کننده آلگوريتم ها‪ ،‬مي‌تواند در مقالة « طرح در رشته‌ها تطبیق مي‌کند » نوشته ال آهو نويسندة ‪grep‬‬

‫يافت شود‪ ( .‬دادرسمي‌های سمپوزيوم در خصوص تئوری زبان رسمي به سانتا باربرا ‪. ) ۱۹۷۹‬‬

‫‪ Sed‬طراحي شد و توسط ال آهو‪ ،‬پیتر و ينبرگر و بر اين کرنیگهان‪ ،‬از طريق يك فرآيند اندکي دقیق‌تر‪ ،‬بکار گرفته شد‪ .‬نام‌گذاری يك‬

‫زبان پس از نويسندگان آن نیز يك کمبود خاص از تصور را نشان مي‌دهد‪ .‬يك مقاله توسط محققان ‪ - Awk‬يك پويش دهي طرح و‬ ‫زبان پردازش؛ نرم افزار‪ -‬تجربه و عمل‪ ،‬جولی ‪ ، ۱۹۷۸‬به بحث و بررسي در خصوص طرح مي‌پردازد‪.‬‬

‫‪ ، awk‬در حیطه‌های متعدد دارای منابع خودش مي‌باشد‪ ،‬اما مطمئنا ً عقايد خوبي را از ‪ ، SNOBOL 4‬از ‪ ، sed‬از يك زبان معتبر‬ ‫طراحي شده توسط مارك روچکايند‪ ،‬از ابزار زبان ‪ lex , yacc‬و البته از زبان ‪ ، c‬به سرقت برده است‪ .‬حقیقتاً‪ ،‬شباهت‌ بین ‪ awk‬و < ‪،‬‬

‫منبع مشکلت مي‌باشدـ ‪ -‬زبان شبیهـ ‪ c‬است اما زبانـ ‪ c‬نیست‪ .‬برخي از ساختارها مفقود هستند؛ سايرساختارها در روشهای دقیق‪،‬‬ ‫متفاوت هستند‪.‬‬

‫يك بند توسط داگ کامر‪ ،‬با عنوان « سیستم فايل ثابت ‪ »FFC‬مي‌باشد ‪:‬‬

‫يك سیستم پايگاه داده‌ها شامل اصول اولیه ( نرم‌افزار ـ عمل و تجربه‪ ،‬نوامبر ‪ ،)۱۹۸۲‬به بحث و بررسي در خصوص استفاده از شل و‬

‫‪ awk‬برای ايجاد يك سیستم پايگاه داده‌ها مي‌پردازد‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪124/322‬‬


‫محیط برنامه سازی لینوکس‬

‫‪125/322‬‬

‫فصل پنجم‪ :‬برنامه‌ریزي پوسته‬ ‫باوجود آنکه اکثر کاربران پوسته را يك عنصر فرمان تبادلي مي‌شمارند‪ ،‬اما در واقع نوعي زبان برنامه‌نويس است که در آن هر عبارت‬

‫فرماني را اجرا مي‌کند‪ .‬از آنجا که بايد هر دو زمینه تبادلي و برنامه‌ريزی اجرای دستور را‪ ،‬تأمین کند‪ ،‬يك زبان غیرعادی است که بیشتر‬ ‫با تاريخچة شکل گرفته تا با طرح‪ .‬محدودة کاربرد آن‪ ،‬حجم نابساماني از جزيیات در زبان برنامه‌نويسي را به همراه دارد‪ .‬اين فصل‪،‬‬

‫مباني برنامه‌ريزی پوسته را به همراه نشان دادن سیر تکامل برخي برنامه‌های پوسته‪ ،‬تشريح خواهد کرد‪ ،‬اما بايد توجه کرد که راهنمايي‬

‫برای پوسته نیست‪ ،‬چنین چیزی در صفحة راهنمای (‪ sh)1‬از راهنمای برنامه نويسان يونیکس‪ ،‬که بايد همواره در حین خواندن کتاب‪،‬‬ ‫آنرا در دسترس داشته باشید‪ ،‬يافت مي‌شود‪.‬‬

‫همچون اکثر دستورات‪ ،‬در پوسته نیز يافتن جزيیات رفتار برنامه‪ ،‬به سرعت و باتجربه‪ ،‬تحقق مي‌يابد‪ .‬راهنمای استفاده مي‌تواند پیچیده‬ ‫باشد‪ ،‬اما هیچ چیز برای درك مسايل‪ ،‬بهتر از يك مثال مناسب نیست‪ .‬بدين منظور‪ ،‬اين فصل بیشتر حول مثالها متمرکز شده تا‬

‫ويژگیهای پوسته و راهنمايي است جهت استفاده از پوسته برای برنامه‌نويسي‪ ،‬نه فقط دايره‌المعارفي از توانائي‌های آن‪ .‬ما تنها در مورد‬ ‫آنچه پوسته مي‌تواند انجام دهد‪ ،‬صحبت نمي‌کنیم‪ ،‬بلکه در مورد توسعه و نوشتن برنامه‌های پوسته‪ ،‬با تأکید بر آزمايش و تبادل نظرات‬ ‫آزمايشي نیز سخن به میان مي‌آوريم‪.‬‬

‫هنگامي که شما يك برنامه را نوشته‌ايد‪ ،‬در پوسته يا در هر زبان ديگر‪ ،‬ممکن است استفاده از آن توسط ساير افراد به قدر کافي مفید‬

‫باشد‪ ،‬اما استانداردهايي که سايرين از يك برنامه انتظار دارند‪ ،‬معمول ً موشکافانه تر از استانداردهای شخص است که در مورد خود به‬ ‫کار مي‌گیرد‪ .‬نمای کلي در برنامه‌نويسي پوسته نیرومند کردن برنامه‌ها به گونه ايست که بتوانند ورودی غیرصحیح را منتقل کرده و به‬

‫هنگام غلط بودن مواردی‪ ،‬اطلعات مفیدی ارايه دهند‪.‬‬ ‫‪ . ۵.۱‬سفارشي کردن دستور ‪cal‬‬

‫يکي از استفاده‌های معمول برنامة پوسته‪ ،‬اصلح يابهبود ارتباط کاربر با برنامه است‪ .‬به عنوان مثالي از يك برنامه که بهبود را نشان دهد‪،‬‬ ‫به فرمان (‪ cal)1‬را توجه کنید‪:‬‬

‫‪Good so far‬‬ ‫‪Not so good‬‬

‫‪$ cal‬‬ ‫‪usage: cal ]month[year‬‬ ‫‪$ cal october 1983‬‬ ‫‪bad argument‬‬ ‫‪$ cal 10 1983‬‬ ‫‪october 1983‬‬ ‫‪S M Tu W Th F S‬‬ ‫‪1‬‬ ‫‪2 3 4 5 6 7 8‬‬ ‫‪9 10 11 12 13 14 15‬‬ ‫‪16 17 18 19 20 21 22‬‬ ‫‪23 24 25 26 27 28 29‬‬ ‫‪30 31‬‬ ‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪126/322‬‬

‫اعمال ماهها بصورت عدد‪ ،‬ايجاد مزاحمت مي‌کند و هنگامي که برگردانیده شود‪ cal 10 ،‬برای کل سال‪ ۱۰ ،‬را چاپ مي‌کند‪ ،‬بنابراين‬ ‫بايد همواره برای مشاهدة تقويم برای يك ماه‪ ،‬سال را مشخص کنید‪.‬‬

‫نکتة مهم در اينجا اين است که فرقي نمي‌کند که فرمان ‪ cal‬چه ارتباطي را تأمین مي‌کند‪ ،‬مي‌توانید بدون تغییر خود ‪ ، cal‬آنرا تغییر‬

‫دهید‪ .‬مي‌توانید دستوری را در دايرکتوری ‪ bin‬شخصي خود‪ ،‬که يك متن مناسبتر را به آنچه ‪ cal‬واقعي نیاز دارد تبديل مي‌کند‪ ،‬قرار‬ ‫دهید‪ .‬حتي مي‌توانید ‪ cal‬نسخة خودرا بازخواني کنید که به معنای يك چیز کمتر برای يادآوری است‪.‬‬

‫اولین قضیه‪ ،‬طراحي است‪ cal :‬چه بايد بکند؟ اصولً ‪ cal‬را برای منطقي بودن نیاز داريم و بايد هر ماه را به اسم بشناسد‪ .‬به دو دلیل ‪،‬‬

‫بايد همانند ‪ cal‬قديمي عمل کند‪ ،‬به جز در مورد برگرداندن نام ماهها به اعداد بنا به آرگومان يك‪ cal ،‬بايد ماه يا تقويم سال را به همان‬

‫درستي چاپ کند و مطابق آرگومان صفر‪ ،‬بايد تقويم جاری را چاپ کند‪ ،‬چرا که اين امر‪ ،‬مطمئنا ً عمده‌ترين استفادة فرمان است‪ .‬پس‬

‫مسئله اين است که تشخیص داده شود که چند آرگومان موجود است و سپس آنها را آنگونه که ‪ cal‬استاندارد نیاز دارد‪ ،‬مطرح کنیم‪.‬‬

‫پوسته‪ ،‬يك عبارت با عنوان ‪ case‬را نیز که مناسب اتخاذ چنین تصمیمهايیست را نیز پیش رو مي‌گذارد‪:‬‬

‫‪Case word in‬‬ ‫;; ‪pattern( commands‬‬ ‫;; ‪pattern( commands‬‬ ‫‪...‬‬ ‫‪esac‬‬

‫عبارت ‪ word,case‬را با نمونه (‪ )pattern‬ها‪ ،‬از بال تا پايین مقايسه مي‌کند و باعث مي‌شود که فرامین‪ ،‬با اولین و تنها اولین نمونه‌ای که‬ ‫مطابقت کند‪ ،‬همراه شوند‪ .‬نمونه‌ها با استفاده از قوانین تطابق نمونة پوسته نوشته مي‌شوند‪ ،‬که تاحدی تعمیم يافتة آنچه مي‌باشند که‬ ‫برای انطباق نام فايلها موجود مي‌باشد‪ .‬هر عمل با دو ; خاتمه يافته است‪ ;;( .‬ممکن است در انتهای آخرين عبارت جايگذاری شده‬

‫باشد‪ ،‬اما برای ويرايش ساده‌تر‪ ،‬معمولً آنرا داخل مي‌گذاريم‪).‬‬

‫نسخة ‪ cal‬ما تصمیم مي‌گیرد که چند آرگومان وجود دارد ‪ ،‬به پردازش الفبايي نام ماهها مبادرت مي‌کند‪ ،‬سپس ‪ cal‬واقعي را فراخواني‬ ‫مي‌کند‪ .‬متغیر پوستة ‪ ، $#‬تعداد آرگومانهايي را که يك فايل پوسته با آنها فراخواني مي‌کند‪ ،‬درخود نگهداری مي‌کند‪ ،‬ساير متغیرهای‬ ‫خاص پوسته‪ ،‬در جدول ‪ ۵-۱‬فهرست شده‌اند‪.‬‬

‫‪)0‬‬ ‫‪)1‬‬

‫‪$ cat cal‬‬ ‫‪$ cal: nicer interface to /use/bin/cal‬‬ ‫‪case $ # in‬‬ ‫‪ # ;; set `date` ; m=$2; y=$6‬هیچ آرگوماني موجود نیست‪ :‬از امروز استفاده مي‌شود‬ ‫‪ # ;; m=$1; set `date`; y=$6‬يك آرگومان‪ :‬از امسال استفاده مي شود‬ ‫دو آرگومان‪ :‬ماه و سال ‪#‬‬

‫;; ‪m=$1; y=$2‬‬

‫;;‬ ‫;;‬ ‫;;‬ ‫;;‬ ‫;;‬

‫‪m=1‬‬ ‫‪m=2‬‬ ‫‪m=3‬‬ ‫‪m=4‬‬ ‫‪m=5‬‬

‫(*‬

‫‪esac‬‬ ‫‪casc $m in‬‬ ‫(*‪jan*|Jan‬‬ ‫(*‪feb*|Feb‬‬ ‫( * ‪mar * | Mar‬‬ ‫(* ‪apr * | Apr‬‬ ‫(*‪may * | May‬‬


‫محیط برنامه سازی لینوکس‬

‫‪127/322‬‬

‫(*‪jun* | Jun‬‬ ‫(*‪jul* | Jul‬‬ ‫(*‪aug* | Aug‬‬ ‫(*‪sep* | sep‬‬ ‫(*‪oct* | oct‬‬ ‫(*‪nov* | Nov‬‬ ‫(*‪dec*| Dec‬‬ ‫;; (‪]1-9[ | 10 |11|12‬‬

‫;; ‪m=6‬‬ ‫;; ‪m=7‬‬ ‫;; ‪m=8‬‬ ‫;; ‪m=9‬‬ ‫;; ‪m=10‬‬ ‫;; ‪m=11‬‬ ‫;; ‪m=12‬‬ ‫ماه به عدد ‪#‬‬

‫سال عادی ‪y=$m; m= '' '' ;; #‬‬

‫(*‬

‫‪esac‬‬ ‫‪/usr/bin/cal $m $y‬‬

‫تقويم واقعي اجرا مي‌شود ‪#‬‬

‫اولین عبارت تعداد آرگوماني را بررسي مي‌کند‪ ، $ # ،‬و عملکرد مناسب را انتخاب مي‌کند‪ .‬نمونة * انتهايي در ‪ case‬اول ‪: catch-all‬‬

‫اگر شمارة آرگومان نه صفر باشد و نه يك‪ ،‬آخر عبارت اجرا خواهد شد‪( .‬از آنجايي که نمونه‌ها به ترتیب جاروب مي‌شوند‪catch-all ،‬‬

‫بايد آخرين باشد‪ ).‬اين امر ‪ y,m‬را برای ماه و سال انتخاب مي‌کند ـ دو آرگومان داده شده و ‪ cal‬ما همانند نمونة اصلي عمل خواهد‬

‫کرد‪.‬‬

‫اولین عبارت‬

‫`‪Set `date‬‬

‫‪ ، case‬دارای يك جفت خط پیچیده شامل‬

‫است‪ .‬باوجود اينکه از ظاهر آن مشخص نیست‪ ،‬اما مي‌توان به سادگي با آزمايش کردن آن دريافت که اين عبارت چه عمل انجام‬ ‫مي‌دهد‪:‬‬

‫جدول ‪ : ۵.۱‬متغیرهای دروني پوسته‬

‫تعداد آرگومانها‬

‫‪$#‬‬

‫تمامي آرگومانهايي که وارد پوسته مي‌شوند‬

‫*‪$‬‬

‫مشابه * ‪ $‬؛ بخش ‪ ۵-۷‬را ببینید‬

‫@‪$‬‬

‫گزينه‌هايي که برای پوسته فراهم شده‌اند‪.‬‬

‫‪$-‬‬

‫مقدار بازگشتي آخرين فرمان اجراشده‬

‫?‪$‬‬

‫شناسايي فرآيند پوسته‬

‫‪$$‬‬

‫شناسايي فرآيند آخرين فرماني که با & آغاز شده‬

‫!‪$‬‬

‫آرگومان پیش فرض برای فرمان ‪cd‬‬

‫‪$Home‬‬

‫فهرست کاراکترهايي که کلمات را در آرگومانها از هم جدا مي‌کنند‬

‫‪$ IFS‬‬

‫فايلي که هنگام تغییريافتن ‪ ،‬پیغام “ ‪ ”you have mail‬را فعال مي‌کند‪.‬‬

‫‪$ MHJL‬‬

‫فهرست دايرکتوريهای جستجوی فرامین‬

‫‪$ PATtl‬‬

‫رشتة فوری‪ ،‬پائین فرض '‪'$‬‬

‫‪$ PS1‬‬

‫رشتة فوری برای خط فرمان ادامه دار‪ ،‬پائین فرض '>'‬

‫‪$ PS2‬‬


‫محیط برنامه سازی لینوکس‬

‫‪128/322‬‬

‫‪$ date‬‬ ‫‪sat oct 1 06 : 05 : 18 EDT 1983‬‬ ‫` ‪$ set ` date‬‬ ‫‪$ echo $1‬‬ ‫‪sat‬‬ ‫‪$ echo $4‬‬ ‫‪06 : 05 :20‬‬ ‫‪$‬‬ ‫‪ set‬يك دستور دروني پوسته است که کارهای بسیاری انجام مي‌دهد‪.‬بدون هیچ آرگوماني‪ ،‬مقدار متغیرها را درمحیط نشان مي‌دهد‪،‬‬

‫همانگونه که در فصل ‪ ۳‬ديديم‪ .‬آرگومانهای متعارف‪ ،‬مقادير ‪ 2$ ، $1‬و غیره را صفر مي‌کند‪ .‬از اين رو ‪ 'set 'date' $‬را برای روز هفته‬

‫انتخاب مي‌کند‪ 2$ ،‬را برای نام ماه و همینطور بقیه‪ .‬بنابراين اولین ‪ case‬در ‪ ،cal‬ماه و سال را از تاريخ جاری تنظیم مي‌کند‪ ،‬درصورتیکه‬ ‫آرگوماني موجود نباشد؛ اگر يك آرگومان داشته باشیم به عنوان ماه در نظر گرفته مي‌شود و سال از تاريخ جاری استخراج مي‌شود‪.‬‬

‫‪ Set‬همچنین چندين گزينه را که اغلب آنها ‪ -x‬و ‪ -V‬مي‌باشند‪ ،‬شناسايي مي‌کند که فرمانهای بازتابي را به موازات پیشبرد توسط پوسته‪،‬‬

‫به کار مي‌اندازند که برای عیب يابي برنامه‌های پیچیدة پوسته‪ ،‬حیاتي مي‌باشند‪.‬‬

‫مسئله‌ای که باقي مي‌ماند‪ ،‬برگرداندن ماه است به عدد‪ ،‬اگر به فرم متني باشد‪ .‬اين امر بوسیله عبارت ‪ case‬دوم انجام مي‌گیرد که بايد‬

‫کامل ً واضح و بديهي باشد‪ .‬تنها دوگانگي اين است که کاراکتر | در عبارت ‪ ، case‬مانند ‪ ، egrep‬دللت بر يك انتخاب دارد‪big | :‬‬

‫‪ small‬منطبق با بر ‪ big‬است يا ‪ . small‬البته اين حالتها‪ ،‬بايد بصورت* ‪ ]jJ[ an‬يا مشابه آن نوشته شوند‪ .‬برنامه اسامي ماهها را هم از‬

‫تمامي قضايای پايینتر دريافت مي‌کند‪ ،‬چرا که بیشتر فرامین‪ ،‬ورودی وضعیت پايین را قبول مي‌کنند‪ ،‬و يا با اولین حرف بزرگ‪ ،‬چرا که‬

‫‪ date‬اين ساختار را چاپ مي‌کند ‪ .‬قاعده‌های تطبیق نمونه‌های پوسته در جدول ‪ ۵ -۲‬آورده شده است‪.‬‬

‫جدول‪ : ۵-۲‬قوانین تطبیق نمونه‌های پوسته‬

‫هر رشته‌ای را مطابقت مي‌دهد‪ ،‬از جمله رشتة خنثي‬

‫*‬

‫هر رشته منفرد را انطباق مي‌دهد‬

‫?‬

‫هر کدام از کاراکترها را د ‪ ccc‬مطابقت مي‌دهد‪.‬‬

‫[‪]CCC‬‬

‫[‪ ]a-do-3‬معادل است با [‪]abcdo123‬‬

‫‪?$‬‬

‫دقیقاًـ … ـراـ ـمطابقتـ ـمي‌دهد؛ـ ـکوتیشن‌ها‪ .‬کاراکترهایـ ـويژهـ ـراـ ـنگهـ ـمي‌دارند‪،‬‬ ‫همچنین '…'‬

‫‪ C‬را جزء به جز تطبیق مي‌دهد‪.‬‬

‫تنها در عبارات ‪ a,case‬يا ‪ b‬را تطبیق مي‌دهد‬ ‫در نام فايلها‪ ،‬آنهايي را که فقط با يك ‪ /‬در عبارات‪ ،‬تطبیق داده شده‌اند؛ در ‪case‬‬

‫هرکدام که مانند ساير کاراکترها مطابقت دارند ‪.‬‬

‫به عنوان اولین کارکتر نام يك فايل ‪ ،‬فقط با يك ‪ 0‬در عبارت تطابق دارد‪.‬‬

‫"…"‬ ‫‪\c‬‬ ‫‪a|b‬‬ ‫‪/‬‬ ‫‪0‬‬

‫دو عبارت آخر در ‪ case‬دوم‪ ،‬دللت بر يك آرگومان ساده دارند که مي‌تواند يك سال باشد‪ ،‬به خاطر بیاوريد که اولین عبارت ‪،case‬‬ ‫آنرا يك ماه فرض کرده بود‪ .‬اگر شماره‌ای باشد که بتواند نشاندهنده ماه باشد‪ ،‬تنها رها مي‌شود‪ ،‬در غیراين صورت به عنوان سال تلقي‬


‫محیط برنامه سازی لینوکس‬

‫‪129/322‬‬

‫مي‌شود‪.‬‬

‫سرانجام‪ ،‬آخرين خط‪ usr/bin/cal ) cal ،‬واقعي ) را با آرگومانهای تغییريافته‪ ،‬فراخواني مي‌کند‪ .‬نسخة ‪ cal‬ما‪ ،‬به گونه‌ای عمل مي‌کند‬ ‫که يك تازه وارد انتظار دارد‪:‬‬

‫‪$ date‬‬ ‫‪sat oct 1 06 : 09 : 55 EDT 1983‬‬ ‫‪$ cal‬‬ ‫‪october 1983‬‬ ‫‪S M Tu W Th F S‬‬ ‫‪1‬‬ ‫‪2 3‬‬ ‫‪4 5 6 7 8‬‬ ‫‪9 10 11 12 13 14 15‬‬ ‫‪16 17 18 19 20 21 22‬‬ ‫‪23 24 25 26 27 28 29‬‬ ‫‪30 31‬‬ ‫‪$ cal dec‬‬ ‫‪December 1983‬‬ ‫‪S M Tu W Th F S‬‬ ‫‪1 2 3‬‬ ‫‪4 5 6‬‬ ‫‪7 8‬‬ ‫‪9 10‬‬ ‫‪11 12 13 14 15 16 17‬‬ ‫‪18 19 20 21 22 23 34‬‬ ‫‪25 26 27 28 29 30 31‬‬ ‫‪$‬‬

‫و‪ ، cal ۱۹۸۴‬تقويم را برای کل ‪ ۱۹۸۴‬چاپ مي‌کند‪.‬‬

‫برنامه ‪ cal‬ارتقا يافتة ما‪ ،‬همان کار را مانند نمونة اصلي انجام مي‌دهد اما با يك روش ساده‌تر و قابل حفظ‌تر‪ .‬از اين رو آنرا بیشتر ‪cal‬‬

‫مي‌خوانیم تا ‪( calendar‬که يك دستورات) يا چیزی که کمتر به ياد مي‌ماند مانند ‪ . ncal‬تنها نهادن اين نام‪ ،‬اين خوبي را دارد که‬

‫کاربران نیاز به توسعه و افزايش بازتابهايي را جهت چاپ تقويم ‪ ،‬ندارند‪.‬‬

‫پيش از آنكه از ‪ case‬بگذريم‪ ،‬بهتر است به خلصه‌اي از اين موضوع بپردازيم كه چرا قوانين‬ ‫تطبيق نمونه‌ها در پوسته متفاوت از آنچه در ‪ ed‬و مشتقات آن مي‌باشند‪ .‬با اين همه‪ ،‬دو‬ ‫نوعت تنمونه‪،‬ت تبهت تمعناي تدوت تمجموعه تقوانينت تبراي تيادگيري توت تدوت تبخش تشامل تكدت تجهت‬ ‫پردازش تآنهات تمي‌باشد‪ .‬برخي تازت تتفاوتها‪،‬گزینه تهای تبعدی تمی تباشند تکه تهرگز تاصلح‬ ‫نشدند‪ ،‬برای مثال هيچ دليلی غير از سازگاری برای این که برای تطبيق هر کاراکتر‪ ed ،‬از‬ ‫نقطه استفاده مي‌كند و پوسته از ? ‪ ،‬نيست‪ .‬اما گاهي نمونه‌ها ‪ ،‬كارهاي متفاوتي انجام‬ ‫مي‌دهند تعبارات تبات تقاعده تدر تويرايشگر‪ ،‬تبهت تدنبال ترشته‌اي تمي‌گردند تكه تممكن تاست‬ ‫هرجاي خط واقع شود؛ كاركترهاي ويژه ^ و ‪ ،$‬جهت اتصال جستجو به ابتدا و انتهاي خط‬ ‫مي‌باشند‪ .‬به هرحال‪ ،‬براي نام فايلها‪ ،‬بايد جستجو را به صورت پيش فرض‪ ،‬تثبيت كنيم‪،‬‬ ‫چرا كه بسيار پيش مي‌آيد كه مجبور باشيم بنويسيم‪:‬‬ ‫‪∧?*. C$‬‬

‫‪1S‬‬

‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪130/322‬‬

‫به جاي‬ ‫‪$‬‬

‫‪1S *.C‬‬ ‫که بسیار ايجاد مزاحمت مي‌کند‪.‬‬

‫تمرين ‪ . ۵-۱‬اگر كاربران نسخة ‪ cal‬شما را ترجيح دهند‪ ،‬براي استفادة جهاني از آن چه‬ ‫تدبيري مي‌انديشيد؟ براي گذاشتن آن در ‪ usr/bin/‬چه بايد كرد؟‬ ‫تمرين ‪ . ۵-۲‬آيا تنظيم ‪ cal‬به گونه‌اي كه ‪ cal ۸۳‬تقويم ‪ ۱۹۸۳‬ترا چاپ كند‪ ،‬ارزشمند مي‬ ‫باشد؟ اگر چنين است‪ ،‬تقويم ‪ ۱۹۸۳‬را چگونه چاپ مي‌كنيد؟‬ ‫تمرين‪ cal . ۵-۳‬را بگونه‌ای تعريف کنید که بیتشر از يك ماه را قبول کند‪ ،‬همانند‪:‬‬ ‫يا درصورت امکان تعدادی از ماهها را‪:‬‬

‫‪$ cal oct nou‬‬ ‫‪$ cal oct – dec‬‬

‫اگر اكنون دسامبر باشد و شمات ‪ cal jan‬را بخواهيد‪ ،‬ژانوية سال جاري را خواهيد ديد يا‬ ‫سال آينده را؟ چه زماني بايد اضافه كردن ويژگيها را به ‪ cal‬متوقف كنيد‪ .‬‬ ‫‪ which    .۲­۵‬كدام دستور است؟‬ ‫در ساختن نسخه‌های خصوصي از دستورهايي مانند ‪ ، cal‬مشکلتي وجود دارد‪ .‬واضح‌ترين مشکل‪ ،‬اين است که اگر با ‪ Mary‬کار‬

‫مي‌کنید و در حالي ‪ cal‬را تايپ کنید که با عنوان ‪ mary‬وارد سیستم شده باشید‪cal،‬استاندارد را به جای نمونة جديد خواهید ديد‪،‬‬

‫البته‌مگر اينکه ‪ Mary cal‬جديد را با دايرکتوری ‪ bin‬خود مرتبط ساخته باشد‪ .‬اين امر مي‌تواند گمراه کننده باشد ـ به خاطر بیاوريد که‬ ‫پیغامهای خطا ازـ ‪ cal‬اصلي‪ ،‬چندان مفید نمي‌باشند ـ اما تنها مي‌تواند مثالي از يك مسئله کلي باشد‪ .‬از آنجايي که پوسته در يك‬ ‫مجموعه از دايرکتوريها که بوسیلة ‪ PATH‬مشخص شده‌اند‪ ،‬به دنبال دستورات مي‌گردد‪ ،‬همیشه امکان اين وجود دارد که به نسخه‌ای از‬

‫يك دستور‪ ،‬غیراز آنچه انتظار داريد‪ ،‬برخورد کنید‪ .‬برای مثال‪ ،‬اگر دستوری را تايپ کنید‪ ،‬فرضا ‪ ، echo‬نام مسیر فايلي که واقعا ً اجرا‬ ‫مي‌شود‪ ،‬مي‌تواند‬

‫‪usr/bin/echo/0 ،‬‬

‫‪ / bin/echo‬يا چیز ديگری باشد‪ ،‬که بستگي به اجزاء ‪ PATH‬و محل قرارگیری فايلها‬

‫دارد‪ .‬وقوع يك فايل اجرايي با نام صحیح اما رفتار اشتباه غیر از آنچه انتظار داريد در جستجو‪ ،‬مي‌تواند گمراه کننده باشد‪ .‬احتمالً‬

‫معمول ترين نمونه‪ ،‬دستور ‪ test‬مي‌باشد که بعدا ً به آن خواهیم پرداخت‪ :‬نام آن برای يك نسخة موقت برنامه‪ ،‬چنان واضح است که‬

‫برنامة ‪ test‬اشتباه‪ ،‬مي‌تواند بطور آزار دهنده‌ای فراخواني شود‪ .‬دستوری که گزارش دهد کدام نسخه برنامه اجرا خواهد شد‪ ،‬بسیار مفید‬ ‫و مورد استفاده خواهد بود‪.‬‬

‫يك شیوة اجرا‪ ،‬حلقه زدن زياد دايرکتوری‌ هايیست که در ‪ PATH‬نام برده شده و جستجوی هرکدام برای يك فايل قابل اجرا است که‬

‫نام آن موجود مي‌باشد‪ .‬درفصل ‪ ، ۳‬از ‪ FOR‬برای حلقه زدن نام فايلها و آرگومانها استفاده کرديم‪ .‬در اينجا‪ ،‬به حلقه‌ای نیاز داريم که‬ ‫بگويد‪:‬‬

‫‪ For i‬در هر جز از ‪PATH‬‬ ‫اگر نام ارائه شده در دايرکتوری‪ i ،‬موجود است‪.‬‬

‫‪do‬‬


‫محیط برنامه سازی لینوکس‬

‫‪131/322‬‬

‫نام کامل سیر آن را چاپ کن‬

‫‪done‬‬ ‫از آنجا که مي‌توانیم هر دستوری را درون '…' اجرا کنیم ‪ ،‬راه حل واضح‪ ،‬اجرا کردن ‪ ،sed‬پیش از ‪ $ PATH‬است و تبديل در نقطه‬ ‫فاصله‪ .‬مي‌توانیم اين موضوع را با دوست قديمیان ‪ echo‬امتحان کنیم‪.‬‬

‫جزء ‪۴‬‬ ‫!تنها ‪ ۳‬چاپ شده‬

‫‪$ echo $ PATH‬‬ ‫‪: usr/you/bin : .bin : / usr/bin‬‬ ‫'‪'s/ : / /g‬‬

‫` ' ‪'s/ : / g‬‬ ‫هنوز فقط ‪3‬‬

‫‪$ echo $ PATH‬‬ ‫‪| sed‬‬ ‫‪/usr / you / bin / bin / usr / bin‬‬ ‫‪$ echo `echo $ PATH | sed‬‬ ‫‪/usr / you / bin / bin / usr / bin‬‬ ‫‪$‬‬

‫به وضوح يك مسئله وجود دارد‪ .‬يك رشتة خنثي در ‪ ،PATH‬مترادف است با « ‪ . » .‬تعويض دو نقطه با فاصله‪ ،‬در ‪ ، PATH‬به قدر‬

‫کافي مناسب نیست ـ اطلعات مربوط به اجزاء خنثي‪ .‬از بین مي روند‪.‬‬

‫بعداً خواهیم ديد که چگونه اين مشکل را در فايلهای پوسته‪ ،‬در جايي که معمولً از ‪ test‬استفاده مي‌شود‪ .‬از بین ببريم‪.‬‬

‫برای ايجاد فهرست صحیح دايرکتوريها‪ ،‬بايد يك جزء بي‌اثر از ‪ PATH‬را به نقطه تبديل کنیم‪ .‬جزء بي‌اثر‪ ،‬مي‌تواند هم در وسط و هم‬

‫در آخر رشته باشد‪ ،‬از اين رو‪ ،‬دستیابي به تمام حالت‪ ،‬کار زيادی نمي‌برد‪:‬‬

‫‪$ echo‬‬ ‫‪$ PATH | sed 's/^ : / . : /‬‬ ‫>‬ ‫‪s/^ : : / : . : /g‬‬ ‫>‬ ‫‪s/^ : $ /: . /‬‬ ‫>‬ ‫'‪s/^ : / /g‬‬ ‫‪. / usr / you / bin / bin / usr / bin‬‬ ‫‪$‬‬

‫مي‌توانستیم آنرا بصورت چهار ‪ sed‬جدا از هم نوشته باشیم‪ ،‬اما از آنجايي که ‪ ، sed‬جابه‌جايي را به ترتیب انجام مي‌دهد‪ ،‬يك تقاضا‬ ‫مي‌تواند تمامي آنها را انجام دهد‪.‬‬

‫هنگامي که اجزاء دايرکتوریـ ‪ PATH‬را داشته باشیم‪ ،‬دستورـ (‪ test)1‬که به آن اشاره کرديم‪ .‬مي ‌تواند اعلم کند که فايلي در هر‬

‫دايرکتوری وجود دارد‪ .‬دستور ‪ test‬درواقع يکي از برنامه‌های خام تز يونیکس مي‌باشد‪ .‬برای مثال‪ test-r file ،‬امتحان مي‌کند که آيا‬

‫‪ file‬وجود دارد و قابل خواندن است و ‪ test-w file‬قابل نوشتن بودن را بررسي‌مي‌کند‪ ،‬اما ويرايش هفتم‪ ،‬هیچگونه ‪ test-x‬را تأمین‬

‫نمي‌کند (باوجود اينکه سیستم ‪ V‬و ساير ويرايش‌ها تأمین مي‌کنند‪ ).‬ما به ‪ test-f‬که امتحان مي کند که فايل موجود است و دايرکتوری‬

‫نیست‪ ،‬به عبارت ديگر‪ ،‬يك فايل با قاعده است‪ .‬به هرحال هنگامي که ويرايشهای گوناگوني موجود باشند‪ ،‬برای ‪ test‬بايد به راهنما‬ ‫مراجعه کرد‪.‬‬

‫هر دستور‪ ،‬يك وضعیت خروج را برمي‌گرداند ـ يك مقدار برای اينکه نشان دهد چه رخ داده ‪ ،‬به پوسته باز مي‌گردد‪ .‬وضعیت خروج‪،‬‬

‫يك رقم کوچك است که طبق قرارداد‪ Q ،‬به معنای «درست» است (دستور به درستي اجراشده) و غیر صفر به معنای «نادرست» است‬


‫محیط برنامه سازی لینوکس‬

‫‪132/322‬‬

‫(دستور با موفقیت اجرا نشده)‪ .‬توجه داشته باشید که اين مقادير‪ ،‬برعکس مقادير درست و نادرست در ‪ C‬مي‌باشند‪.‬‬

‫از آنجايیکه بسیاری مقادير‪ ،‬مي‌توانند دللت بر «نادرست» داشته باشند‪ ،‬علت نقص‪ ،‬اغلب در وضعیت خروج «نادرست» رمز مي‌شود‪،‬‬ ‫برای مثال‪ ،‬درصورت وجود تطابق‪،‬‬

‫‪ grep‬مقدار صفر را برمي گرداند و اگر تطبیقي پیش نیايد‪ ،‬يك و اگر اشتباهي در نام فايل يا‬

‫نمونه باشد‪ .۲ ،‬هر برنامه‪ ،‬وضعیتي را برمي‌گرداند‪ ،‬هرچند معمول ً مقدار آن جالب توجه ما نیست‪ test .‬در اين مورد‪ ،‬غیر معمول عمل‬ ‫مي‌کند چرا که وظیفة اصلي آن‪ ،‬برگرداندن وضعیت خروج است و هیچ خروجي ايجاد نکرده و تغییری در هیچ فايلي نمي‌دهد‪.‬‬

‫پوسته وضعیت خروج آخرين برنامه را در متغیر ?‪ $‬نگهداری مي‌کند‪:‬‬

‫‪cmp/usr/you/ .profile / usr / you / . profile‬‬ ‫هیچ خروجي ‪ :‬مشابهند‬

‫‪$‬‬ ‫‪$‬‬

‫? ‪$ echo $‬‬ ‫‪0‬‬ ‫‪Zero implies ran O.K .: files identical‬‬ ‫‪$ cmp / usr /you / . profile / usr / mary /. profile‬‬ ‫‪/ usr /you /.profile /usr /mary /.profile / usr / mary /. profile differ : char 6, line 3‬‬ ‫? ‪$ echo $‬‬ ‫‪1‬‬ ‫غیرصفر به معنای تفاوت فالهايست‬ ‫‪$‬‬

‫تعدادی از دستورات مانند ‪ cmp‬و ‪ ، grep‬دارای يك گزينة ‪ S‬ـ مي‌باشند که باعث خروج آنا با يك وضعیت صحیح مي‌شود اما تمامي‬ ‫خروجي‌ها متوقف مي‌کند‪.‬‬

‫عبارت ‪ if‬پوسته‪ ،‬فرامیني را اجرا مي‌کند که براساس وضعیت خروج يك دستور مي‌باشند‪ ،‬مانند‬ ‫دستور‬

‫‪if‬‬

‫دستور مي‌دهد‪ ،‬اگر شرط درست باشد‬ ‫دستور مي‌دهد اگر شرط نادرست باشد‬

‫‪then‬‬ ‫‪else‬‬ ‫‪fi‬‬

‫موقعیت خطوط جديد‪ ،‬دارای اهمیت مي‌باشد‪ fi ، then :‬و ‪ else‬تنها پس از يك خط جديد يا نقطه ويرگول شناخته مي‌شوند‪else .‬‬

‫اختیاری مي‌باشد‪.‬‬

‫جملة ‪ ، if‬همواره دستوری را اجرا مي‌کند ـ شرطي را ـ در حالي که جمله ‪ ، case‬تطبیق نمونه را مستقیما ً درپوسته به عهده دارد‪.‬‬

‫دربرخي ويرايشهای يونیکس‪ ،‬که شامل ‪ V Sysetem‬نیز مي‌باشند‪ test ،‬تابعي دروني از پوسته است از اينرو‪ ،‬يك ‪ if‬و يك ‪ ، test‬به‬

‫سرعت يكـ ‪ case‬عمل مي‌کنند‪ .‬اگرـ ‪ test‬دروني نباشد‪ ،‬جملتـ ‪ case‬کارامدتر از جملت ‪ if‬مي‌باشند و بايد برای هر نوع تطبیق‬ ‫نمونه‌ای مورد استفاده قرار گیرند‪:‬‬

‫‪"$/" in‬‬ ‫‪hello ( command‬‬ ‫‪esac‬‬ ‫‪Will be faster than‬‬

‫‪Case‬‬


‫محیط برنامه سازی لینوکس‬

‫‪133/322‬‬

‫‪if tset '' $1'' = hello‬‬ ‫کندتر مگر آنکه ‪ test‬دستوری دروني در پوسته باشد‬

‫‪then‬‬

‫‪command‬‬ ‫‪fi‬‬

‫يك دلیل برای اينکه گاهي از جملت ‪ ،case‬برای امتحان کارهايي که در پوسته بوسیلة يك جمله ‪ if‬در اغلب زبانهای برنامه نويسي‬ ‫انجام مي‌گیرد‪ ،‬وجود دارد‪ .‬از طرف ديگر‪ ،‬يك جملة ‪ ،case‬نمي‌تواند به سادگي تشخیص دهد که فايلي ‪ ،‬مقادير مجاز را خوانده باشد؛‬ ‫که بهتر است بوسیله يك ‪ test‬و ‪ if‬انجام گیرد‪.‬‬

‫از اين رو همه چیز برای اولین نخسه از فرمان ‪ ، which‬سر جای خودش است؛ برای نشان دادن اينکه کدام فايل به يك دستور پاسخ‬ ‫مي‌دهد‪:‬‬

‫‪$ cat which‬‬ ‫‪# Which cmd : Which cmd in PATH is executed , version 1‬‬ ‫‪case $ # in‬‬ ‫‪0( echo 'usage : Which command' 1>&2 ; exit 2‬‬ ‫‪esac‬‬ ‫‪for i in ` echo $ PATH | ' s / ^ : / . : /‬‬ ‫‪s / : : / : . : /g‬‬ ‫‪s / :$ / : . /‬‬ ‫` '‪s/:/ /g‬‬ ‫‪do‬‬ ‫‪if test – f $i /$1‬‬ ‫‪# use test -x if you can‬‬ ‫‪then‬‬ ‫‪echo $i /$1‬‬ ‫‪exit 0‬‬ ‫‪# found it‬‬ ‫‪fi‬‬ ‫‪done‬‬ ‫‪exit 1‬‬ ‫‪# not found‬‬ ‫‪$‬‬ ‫‪:‬آنرا امتحان مي‌کنیم‬ ‫آنرا قابل اجرا مي‌کند‬

‫‪$ cx which‬‬ ‫‪$ Which Which‬‬ ‫‪. / Which‬‬ ‫‪$ which ed‬‬ ‫‪/ bin / ed‬‬ ‫‪$ mv Which / usr / you / bin‬‬ ‫‪$ Which Which‬‬ ‫‪/ usr / you / bin / Which‬‬ ‫‪$‬‬

‫جملة ‪ case‬مبنا‪ ،‬تنها بررسي خطا را به عهده دارد‪ .‬به جهت يابي دوبارة ‪ 1>82‬در ‪ echo‬توجه فرمايید‪ ،‬که پیغام خطا‪ ،‬مسیر را محو‬


‫محیط برنامه سازی لینوکس‬

‫‪134/322‬‬

‫نمي‌کند‪ ،‬دستور دروني پوستة ‪ ، exit‬مي‌تواند به منظور برگرداندن يك وضعیت خروج مورد استفاده قرار گیرد‪ .‬م ا ‪ exit 2‬را برای‬ ‫برگرداندن يك وضعیت خطا درصورتي که دستور کار نمي‌کرد‪ exit 1 ،‬اگر نمي‌توانست فايل را پیدا کند و ‪ exit 0‬اگر يکي را پیدا‬

‫مي‌کرد‪ .‬اگر هیچ جملة ‪ exit‬صريحي وجود نداشته باشد‪ ،‬وضعیت خروج از فايل پوسته‪ ،‬وضعیت آخرين دستور اجرا شده است‪.‬‬

‫چه اتفاقي رخ مي‌دهد اگر برنامه‌ای داشته باشید که نام آن در دايرکتوری جاری ‪ test‬باشد؟‬

‫(فرض مي‌کنیم که ‪ test‬دستور دروني از پوسته نیست‪).‬‬ ‫يك ‪ Test‬حلقه ايجاد مي‌کند‪ .‬آنرا قابل اجرا مي‌کند‪.‬‬

‫آنرا قابل اجرا مي کند‬ ‫‪Which Which $‬‬ ‫مردود مي شود !‬

‫‪$ echo 'echo hello′ >test‬‬ ‫‪$ cx test‬‬ ‫را امتحان مي کند ‪ Which‬حال‬ ‫‪hello‬‬ ‫‪. /Which‬‬ ‫‪$‬‬

‫بررسي خطای بیشتری فراخواني مي‌شود‪ .‬مي‌توانستیدـ ‪ which‬را به منظور يافتن نام کامل مسیر برایـ ‪ test‬اجرا کنیدـ (اگرـ ‪ test‬در‬ ‫دايرکتوری جاری نبود)‪ ،‬و آنرا صراحتاً مشخص کنید‪ .‬اما قانع کننده نیست‪ test :‬ممکن است در دايرکتوری‌های مختلف در سیستمهای‬

‫مختلفي باشد و ‪ which‬نیز بستگي به ‪ echo‬و ‪ sed‬دارد‪ ‌ ،‬از اين رو بايد نام مسیرهای آنها را نیز مشخص کنیم‪ .‬يك راه حل ساده‌تر‬ ‫وجود دارد‪ PATH :‬را در فايل پوسته تنظیم کنید‪ ،‬تا فقط در ‪ bin /‬و ‪ usr/bin/‬برای دستورات باشد ‪ .‬البته‪‌ ،‬تنها برای دستور ‪،which‬‬

‫مجبور به ذخیرة ‪ PATH‬پیشین برای تعیین توالي دايرکتوری‌هايي که بايد جستجو شوند مي‌باشید‪.‬‬

‫‪$ cat which‬‬ ‫‪# Which cmd : Which cmd in PATH is executed , final version‬‬ ‫‪opath = $ PATH‬‬ ‫‪PATH = / bin : / usr / bin‬‬ ‫‪case $ # in‬‬ ‫(‪0‬‬ ‫‪echo ' Usage : Which command ' 1 > & 2 ; exit 2‬‬ ‫‪esac‬‬ ‫‪for i in ` echo $ opath | sed 's / ^ : / . : /‬‬ ‫‪s/::/:.:/g‬‬ ‫‪s/:$/:./‬‬ ‫` '‪s / : / /g‬‬ ‫‪do‬‬ ‫‪if test – f $ i / $1‬‬ ‫‪# this is / bin / test‬‬ ‫‪then‬‬ ‫‪# or / usr / bin / test only‬‬ ‫‪echo $i / $1‬‬ ‫‪exit 0‬‬ ‫‪# found it‬‬ ‫‪fi‬‬ ‫‪done‬‬ ‫‪exit 1‬‬ ‫‪# not found‬‬ ‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪135/322‬‬

‫اکنون ‪ which‬حتي اگر يك ‪( Test‬يا ‪ sed‬يا ‪ ) echo‬جعلي نیز در خلل جستجو وجود داشته باشد‪ ،‬عمل مي کند‪.‬‬

‫‪still there‬‬

‫‪$ 1S – 1 test‬‬ ‫‪rwxrwxrwx 1 you‬‬ ‫‪11 oct 1 06:55 test‬‬ ‫‪$ which which‬‬ ‫‪/ usr / you / bin / which‬‬ ‫‪$ which test‬‬ ‫‪. / test‬‬ ‫‪$ rm test‬‬ ‫‪$ which test‬‬ ‫‪/ bin / test‬‬ ‫‪$‬‬

‫پوسته دو عملگر ديگر را نیز برای ترکیب فرامین‪ ،‬تأمین مي‌کند‪ ¦¦ ،‬و && ‪ ،‬که اغلب فشرده‌تر و راحت‌تر از جملة ‪ if‬مي‌باشند‪ .‬برای‬ ‫مثال ¦¦ مي‌تواند برخي جملت ‪ if‬را جابجا مي‌کند‪:‬‬

‫‪ dose not exist‬نام فايل ‪ ¦¦ echo file‬نام فايل ‪ test - f‬معادل است با‪:‬‬

‫! شرط را منفي مي‌کند‪.‬‬

‫نام فايل ‪if test ! – f‬‬

‫‪echo file filename dose not exist‬‬

‫‪then‬‬ ‫‪fi‬‬

‫عملگر ¦¦‪ ،‬علي رقم ظاهر آن‪ ،‬هیچ ربطي به لوله‌ها ندارد ـ عملگری است شرطي به معنای ‪. OR‬‬

‫دستور سمت چپ ¦¦ به اجرا درخواهد آمد‪ .‬اگر وضعیت خروج آن‪ ،‬صفر باشد‪( ،‬موفقیت)‪ ،‬دستور سمت راست ¦¦ ناديده گرفته مي‌شود‪.‬‬

‫اگر سمت چپ‪ ،‬مقداری غیر صفر را برگرداند (عیب) سمت راست اجرا شده و مقدار کل عبارت‪ ،‬وضعیت خروج سمت راستي خواهد‬ ‫بود‪ .‬به عبارت ديگر‪ ¦¦ ،‬يك عملگر ‪ OR‬شرطي است که دستور سمت راست خود را در صورت موفقیت سمت چپ‪ ،‬اجرا نمي‌کند‪.‬‬

‫&& شرطي پاسخ‪ AND ،‬مي‌باشد؛ دستور سمت راست خود را خود را تنها هنگامي اجرا مي‌کند که سمت چپي موفقیت آمیز باشد‪.‬‬

‫تمرين ‪ . ۵-۴‬چرا ‪ PATH Which‬را به ‪ ،Opath‬قبل از خروج مقدار دهي اولیه نمي‌کند؟‬

‫تمرين ‪ . ۵-۵‬از آنجائیکه پوسته از ‪ esac‬برای پايان دادن به يك ‪ case‬استفاده مي‌کندو از ‪ fi‬برای اتمام يك ‪ ، if‬چرا از ‪ done‬برای اتمام‬

‫‪ do‬استفاده مي‌کند؟‬

‫تمرين‪ . ۵-۶‬يك گزينه ‪ a‬ـ را به ‪ which‬اضافه کنید‪.‬بگونه‌ای که تمامي فايلها را در ‪ PATH‬چاپ کند به جای اينکه بعد از اولین فايل‪،‬‬ ‫خارج شود‪ .‬راهنمايي‪match=´exit O´ . :‬‬

‫تمرين ‪ Which . ۵-۷‬را بگونه‌ای تعريف کنید که فرامین درون پوسته مانند ‪ exit‬را بشناسد‪.‬‬

‫تمرين ‪ Which. ۵-۸‬را بگونه ای تعريف کنید که مجاز بودن اجرا را روی فايلها بررسي ‌کند‪ .‬آنرا جهت چاپ يك پیغام خطا هنگام‬ ‫نیافتن يك فايل‪ ،‬تغییر دهید‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪136/322‬‬

‫‪ ۵­۳‬حلقه‌هاي ‪ while‬و ‪ : Loop‬مراقبت از اشياء‬ ‫در فصل سوم‪ ،‬از حلقه ‪ for‬برای برخي برنامه‌های تبادلي ساده استفاده مي‌شود‪ .‬معمولً ‪ For‬حول مجموعه‌ای از نام فايلها حلقه مي‌زند‪‌،‬‬

‫مانند '‪ ً For i in *.c‬يا هر برهاني در برنامه پوسته همانند' *‪ . 'i in For $‬اما حلقهة‌ای پوسته کلي تر از اين تعابیر هستند؛ حلقة ‪ for‬را‬ ‫در ‪ Which‬در نظر آوريد‪.‬‬

‫سه نوع حلق وجود دارد‪ for . until , while , for :‬دارای بیشترين استفاده است و مجموعه ای از دستورات را اجرا مي‌کند – بدنة‬ ‫حلقه ـ يکبار برای هر عضوی از مجموعه کلمات که اغلب آنها نام فايلهاست‪.‬‬

‫‪ Until – while‬وضعیت خروج را از يك دستور‪ ،‬برای کنترل اجرای دستورات بدنه حلقه به کار مي‌برد‪.‬‬

‫بدنة حلقه تا هنگامي اجرا مي‌شود که دستور شرط‪ ،‬يك مقدار غیر صفر را (برای ‪ ) while‬يا صفر (برای ‪ ) unit‬باز گرداند‪ While .‬و‬ ‫‪ ، unit‬مگر برای تفسیر وضعیت خروج دستور‪ ،‬قابل تشخیص مي‌باشند‪.‬‬

‫در اينجا فرم پاية هر حلقه آورده شده است‪:‬‬

‫فهرست کلمات‬

‫‪for I in‬‬

‫‪do‬‬

‫تنظیم از روی عناصر متوالي فهرست ‪ ، $i‬بدنه حلقه‬

‫‪done‬‬ ‫(فهرست ‪ ،‬تمامي آرگومانهای فايل پوسته است‪ ‌،‬برای مثال ‪for i ) * $ ،‬‬ ‫‪do‬‬

‫بدنه حلقه ‪ i $ ،‬به آرگومانهای متوالي تنظیم مي شود‪.‬‬

‫‪Done‬‬ ‫‪While‬‬

‫دستور‬

‫‪do‬‬

‫بدنه حلقه‌ها را که دستور مقدار درست را بر مي‌گرداند اجرا مي‌شود‪.‬‬

‫‪Done‬‬ ‫‪until‬‬

‫دستور‬

‫‪do‬‬

‫بدنه حلقه تا جايي که دستور مقدار نادرست را بر مي‌گرداند‪ ‌،‬اجرا مي‌شود‬

‫‪Done‬‬

‫دومین فرم ‪ for‬که در آن يك فهرست خالي‪ ‌ ،‬دللت بر *‪ $‬مي‌کند‪‌ ،‬خلصه نويسي است برای بسیاری استفاده‌های معمول‪‌ .‬دستور‬

‫شرطي که ‪ while‬يا ‪ until‬را کنترل مي‌کند‪ ،‬مي‌تواند هر دستوری باشد‪ .‬يك مثال جزيي‪‌ ،‬حلقة ‪ Loop‬است که منتظر مي‌ماند تا کسي‬ ‫وارد سیستم شود (‪:)Mary‬‬

‫‪While sleep 60‬‬ ‫‪do‬‬ ‫‪Who | grep mary‬‬ ‫‪dcne‬‬

‫‪ Sleep‬كه توقفي ‪ 60‬ثانيه ايجاد مي‌كند‪‌ ،‬در حالت عادي همواره اجرا مي‌شود (مگر اينكه‬


‫محیط برنامه سازی لینوکس‬

‫‪137/322‬‬

‫قطع گردد) و از اين روت «موفقيت» را بر مي‌گرداند‪‌ ،‬ت سپس حلقه هر يك دقيقه يك بار‬ ‫بررسي مي‌كند كه آيا ‪ Mary‬وارد شده يا نه‪.‬‬ ‫اين نسخه داراي اين نقص مي‌باشد كه اگر ‪ Mary‬در حال حاضر وارد شده باشد‪ ،‬بايد ‪60‬‬ ‫ثانيه صبر كنيد تا متوجه شويد‪.‬‬ ‫همچنين اگر ‪ mary‬در اين حال بماند‪ ،‬هر يك دقيقه يكبار از وضعيت آن‪‌ ،‬مطلع خواهيد شد‪.‬‬

‫محتويات حلقه را مي‌توان بيرون آورده و با ‪ until‬نوشت تا اطلعات را يكبار و بدون تأخير‬ ‫تأمين كرد‪ ،‬اگر ‪ mary‬اكنون وارد شده باشد‪:‬‬ ‫‪until who ¦ grep mary‬‬ ‫‪do‬‬ ‫‪sleep 60‬‬ ‫‪done‬‬ ‫اين شرط‪ ،‬جالب‌تر مي‌باشد‪ ،‬اگر ‪ Mary‬وارد شده باشد‪ ’who |grep mary’ ‌،‬مشخصات ورود او را در فهرست بندی ‪ who‬چاپ کرده‬ ‫و ً درست ً را بر مي‌گرداند‪ ،‬چراکه ‪ grep‬يك وضعیت را جهت نشان دادن اين که چیزی را يافته‪ ،‬بر مي‌گرداند‪.‬‬

‫سرانجام‪ ،‬اين دستور را پوشش داده‪ ،‬به آن اسمي مي‌دهیم و آنرا نصب مي‌کنیم‪.‬‬

‫‪$ cat watchfor‬‬ ‫‪# watchfor : watch for sommeone to log in‬‬ ‫‪PATH = / bin : / usr / bin‬‬ ‫‪case $ # in‬‬ ‫(‪0‬‬ ‫‪echo ' Usage : watchfor person' 1 > &2 ; exit 1‬‬ ‫‪esac‬‬ ‫'' ‪until who \ egrep '' $ 1‬‬ ‫‪do‬‬ ‫‪sleep 60‬‬ ‫‪done‬‬ ‫‪$ cx watchfor‬‬ ‫‪$ watchfor you‬‬ ‫‪you‬‬ ‫‪ttyo‬‬ ‫کار مي کند ‪oct 1 08:01‬‬ ‫آنرا نصب مي کند‬

‫‪mv watchfor / usr / you / bin‬‬

‫‪$‬‬ ‫‪$‬‬

‫‪ grep‬را با ‪ egrep‬تعويض کرديم‪ ،‬پس مي‌توان نوشت‪ ´watch for ´joe | mary $ :‬تا ورود بیشتر از يك نفر را کنترل کند‪.‬‬

‫به عنوان يك مثال پیچیده‌تر‪ ،‬ورود و خروج تمامي افراد را زير نظر مي‌گیريم وهر گاه افرادی وارد يا خارج شوند‪ ،‬گزارشي ارائه مي‬ ‫دهیم ‪ -‬نوعي ‪ who‬افزايشي‪ ،‬ساختار پاية آن‪ ،‬ساده است‪ :‬هر يك دقیقه‪ ‌who،‬اجرا مي شود‪ ،‬خروجي آن با يك دقیقه قبل مقايسه مي‬

‫شود و هر گونه اختلفي‪ ،‬گزارش مي شود‪ .‬خروجي ‪ ، Who‬در يك فايل نگهداری مي‌شود تا بتوان آنرا در دايرکتوری ‪ / tmp‬ذخیره‬

‫کرد‪ .‬برای تشخیص فايلهای خود از فايلهای مربوط به ساير پردازشها‪ ،‬متغیر پوسته ‪( $$‬شناسة پردازش دستور پوسته) با نام فايل ترکیب‬


‫محیط برنامه سازی لینوکس‬

‫‪138/322‬‬

‫مي‌شود که قراردادی متداول است‪ .‬رمز کردن نام دستور در فايلهای موقتي‪ ،‬اکثرا ً برای مدير سیستم انجام مي‌پذيرد ‪ .‬دستورات ( شامل‬

‫اين نسخه از ‪ ) watch who‬اغلب فايلها را در ‪ ،/tmp‬رها مي‌کند و جالب است بدانید که کدام دستور اين کار را انجام مي‌دهد ‪.‬‬

‫‪$ cat watch who‬‬ ‫‪# watchwho : watch who logs in and out‬‬

‫‪PATH = / bin : / usr / bin‬‬ ‫‪new = / tmp / wwho 1 . $$‬‬ ‫‪old = / tmp / wwho 2 . $$‬‬ ‫‪> $ old‬‬ ‫‪# create an ampty file‬‬ ‫‪while :‬‬ ‫‪# lopp forever‬‬ ‫‪do‬‬ ‫‪who > $ new‬‬ ‫‪diff $old $new‬‬ ‫‪mv $new $old‬‬ ‫‪sleep 60‬‬ ‫‪done | awk ' / >/ } $1 = ''in :‬‬ ‫{ ‪'' ; print‬‬ ‫‪/ < / } $1 = ''out :‬‬ ‫' { ‪'' ; print‬‬ ‫‪$‬‬ ‫"‪ ":‬يك دستور درون پوسته است که کاری به جز نشان دادن برهانهای خود و برگرداندنـ " درست" انجام نمي‌دهد‪ .‬در عوض‪،‬‬

‫مي‌توانستیم از دستور ‪ true‬که خود يك وضعیت خروج صحیح را بر مي‌گرداند استفاده کنیم‪( ،‬همچنین يك دستور ‪ false‬نیز وجود‬ ‫دارد) ‪ .‬اما "‪ ":‬مؤثرتر از ‪ true‬است چرا که دستور را از سیستم فايل اجرا نمي‌کند‪.‬‬

‫خروجي ‪ ، diff‬از > و < برای تشخیص داده‌ها از دو فايل استفاده مي‌کند‪ .‬برنامه ‪ awk‬اين مورد را برای گزارش تغییرات بصورتي‬

‫بسیار ساده برای يادگیری‪ ،‬پردازش مي‌کند‪ .‬توجه کنید که کل حلقه ‪ ، while‬به ‪ awk‬مرتبط است‪ ،‬به جای اينکه يك ‪ awk‬تازه را هر‬ ‫از يك دقیقه اجرا کند‪ Sed .‬برای اين پردازش مناسب نمي‌باشد‪ ،‬چرا که خروجي آن همواره عقب تر از ورودی آن در يك خط است‪:‬‬ ‫همواره يك خط ورودی وجود دارد که پردازش مي‌شود اما چاپ نمي‌شود‪ ،‬و اين امر باعث تأخیری ناخواسته مي‌گردد‪.‬‬

‫به دلیل اينکه ‪ old‬خالي ايجاد شده است‪‌،‬اولین خروجي از ‪‌ ، Watchwho‬فهرستي از تمامي کار براني است که در حال حاضر وارد‬

‫شده‌اند‪ .‬تغییر دادن دستوری که ‪ old‬را مي‌سازد‪ ،‬به ‪ ‌ ،who > $old‬باعث مي‌شود‪ Watchwho .‬تنها تغییرات را چاپ کند؛ که امری‬ ‫است اختیاری‪.‬‬

‫يك برنامة حلقة ديگر ‪ ،‬برنامه‌ايست که متناوبا ً به ‪ mailbox‬شما نگاه مي‌کند؛ هر گاه تییر کند‪ ‌،‬برنامه “ ‪ ''You have mail‬را چاپ‬ ‫مي‌کند که جايگزيني است مناسب برای مکانیزم ‪‎‬دروني پوسته که از متغیر ‪ MAIL‬استفاده مي‌کند‪ .‬ما آنرا با متغیرهای پوسته به جای‬

‫فايلها به کار گرفتیم‪ ،‬تا راهي متفاوت برای انجام کارها را نشان دهیم‪.‬‬

‫‪$ cat checkmail‬‬ ‫‪# checkmail :‬‬ ‫‪watch mailbox for growth‬‬ ‫‪PATH = / bin : / usr / bin‬‬ ‫‪MAIL = / uar / spool / mail / `getname ` # system dependent‬‬ ‫{ ‪t = $ } 1 – 60‬‬ ‫'' ` ‪x= '' ` 1s – 1 $ MAIL‬‬ ‫‪while :‬‬ ‫‪do‬‬


‫محیط برنامه سازی لینوکس‬

‫‪139/322‬‬

‫''`‪y = '' ` 1s -1 $ MSIL‬‬ ‫‪echo $ x $ y‬‬ ‫''‪x = ''$y‬‬ ‫‪sleep $t‬‬ ‫'{ '' ‪done | awk ' $4 < $1 } print ''you have mail‬‬ ‫‪$‬‬ ‫دوباره از ‪ ، awk‬اينبار برای اطمینان از اينکه پیغام تنها هنگامي که ‪ mail box‬زياد شود چاپ شود و نه هنگامي که تنها تغییر کند‪،‬‬

‫استفاده کرديم‪ .‬در غیر اين صورت‪ ،‬دقیقا ً بعد از حذف يك ‪ ، mail‬پیغامي مشاهده خواهید نمود‪( .‬ويرايش دروني پوسته از اين نقطه‪،‬‬ ‫دارای ضعف است)‪.‬‬

‫ساعت دروني‪ ‌،‬به طور معمول روی ‪ 60‬ثانیه تنظیم شده‪ ،‬اما اگر پارامتری در خط دستور باشد‪ ،‬مانند‪:‬‬

‫‪cat checkmail 30 $‬‬

‫اين زمان به جای قبلي استفاده مي‌شود‪ .‬متغیر پوسته ‪ ‌ ، t‬در صورتي زماني اعمال شود‪ ،‬مقدار آنرا مي‌گیرد و اگر مقداری داده نشود‪،‬‬ ‫همان ‪ 60‬را از خط ‪:‬‬

‫‪} t = $ } 1 – 60‬‬ ‫مي‌گیرد‪ .‬اين موضوع‪ ،‬ويژگي ديگری از پوسته را معرفي مي‌کند‪.‬‬

‫{‪ $}var‬معادل است با ‪ $ var‬و مي‌تواند جهت صرف نظر کردن از مسائل ناشي از متغیرهای درون رشته‌های شامل حروف يا اعداد‪،‬‬ ‫به کار رود‪:‬‬

‫‪$ var = hello‬‬ ‫‪$ varx=goodbye‬‬ ‫‪$ echo $ var‬‬ ‫‪hello‬‬ ‫‪$ echo $ varx‬‬ ‫‪goodbye‬‬ ‫‪$ echo $ }var {x‬‬ ‫‪hellox‬‬ ‫‪$‬‬

‫کاراکترهای خاص درون براکتها‪ ،‬پردازش ويژه متغیرها را مشخص‌ مي‌کند‪ .‬اگر متغیر تعريف نشده باشد و در پي نام آن علمت سؤال‬

‫آمده باشد‪ ،‬رشتة بعد از ؟ چاپ مي‌شود و پوسته خارج مي‌شود (مگر اينکه تباد لي‌ باشد) ‪ .‬اگر پیغام خاصي مهیا نشده باشد‪‌،‬استاندارد‬

‫آن بصورت زير چاپ مي‌شود‪:‬‬

‫‪O.K.;var is set‬‬ ‫پیغام پیش فرض‬ ‫پیغام اعمال شده‬

‫‪$ echo‬‬ ‫{? ‪$ }var‬‬ ‫‪hello‬‬ ‫{?‪$ echo $ } junl‬‬ ‫‪junk : parameter not set‬‬ ‫{ !‪$ echo $ } junk?error‬‬ ‫! ‪junk : error‬‬

‫توجه داشته باشید که پیغامي که توسط پوسته ساخته مي‌شود‪ ‌،‬همواره شامل نام متغیر تعريف نشده است‪.‬‬

‫‪$‬‬


‫محیط برنامه سازی لینوکس‬

‫‪140/322‬‬

‫يك فرم ديگر‪ $ }Var-thing { ،‬مي‌باشد که آنرا با ‪ $ Var‬ارزيابي مي‌کند‪ ،‬اگر تعريف شده باشد و با ‪ ، thing‬اگر تعريف شده نباشد‪.‬‬

‫{ ‪ $ }Var = thing‬نیز مشابه است‪ ،‬اما ‪ thing‬را نیز با ‪ $ Var‬مقدار دهي مي‌کند‪:‬‬

‫‪ junk‬تأثیر نپذيرفته است‬

‫‪ Hi , junk‬مقدار دهي شده‬

‫{ ' ‪$ echo $ }junk- 'Hi there‬‬ ‫{?‪Hi echo $ }junk‬‬ ‫‪junk : parameter not set‬‬ ‫{' ‪$ echo $ } junk= 'Hi there‬‬ ‫‪Hi there‬‬ ‫{ ?‪$ echo $ } junk‬‬ ‫‪Hi there‬‬ ‫‪$‬‬

‫قوانین ارزيابي متغیرها‪ ،‬در جدول ‪ ۵-۳‬آمده است‪.‬‬

‫بر مي‌گرديم به مثال ساده خودمان‪t = $ } 1-60 {،‬‬

‫‪ t‬را از روي ‪ ، $1‬يا اگر هيچ آلگومان اعمال نشده باشد ‪،‬‬ ‫جدول ‪ :۵-۳‬ارزيابي متغیرهای پوسته‬

‫‪ 60‬مقدار دهي مي‌کند‪.‬‬ ‫‪$ Var‬‬ ‫{‪$ } Var‬‬ ‫{‪$ } Var-thing‬‬

‫مقدار ‪ Var‬؛ اگر ‪ Var‬تعريف نشده باشد‪ ،‬هیچ مقداری‬

‫مشابه است؛ اگر بعد از متغیر نام ‪ ،‬حروف و ارقام آورده شود‪.‬‬

‫اگر تعريف شده باشد‪ ،‬مقدار ‪ Var‬و در غیر اين صورت ‪ thing $ Var ،‬تغییر {‪$ } Var = thing‬‬ ‫نمي‌يابد‪.‬‬

‫اگر تعريف شده باشد‪ ،‬مقدار ‪ Var‬و در غیر اين صورت ‪$ Var ،‬‬

‫‪ thing‬نمي‌يابد‪.‬‬

‫‪ thing‬مقدار {‪$}var?message‬‬

‫اگر تعريف شده باشد‪ . $ Var ،‬در غیر اين صورت‪ message ،‬را چاپ کرده و از‬

‫‪$ }Var+thing{$‬‬

‫پوسته خارج مي‌شود‪ .‬اگر ‪ message‬خالي باشد‪ ،‬چاپ مي‌کند‪Var: parameter :‬‬

‫‪not set‬‬

‫اگر ‪ $ Var‬تعريف شده باشد‪ thing ،‬و در غیر اين صورت هیچ چیز‬ ‫تمرين ‪ .۵-۹‬به کاربرد ‪ true‬و ‪ False‬در ‪ bin /‬يا ‪ user /bin /‬توجه کنید‪ .‬چگونه مي‌توانید متوجه شويد چگونه کار مي‌کنند؟‬

‫تمرين ‪ Water for . ۵-۱۰‬را بگونه‌ای تغییر دهید که برهانهای گوناگوني به عنوان افراد تلقي گردند‪ ،‬به جای اينکه نیاز باشد کاربر ´‪Joe‬‬ ‫‪ ´| mary‬را تايپ کند‪.‬‬

‫تمرين ‪ . ۵-۱۱‬نسخه‌ای از ‪ watchwho‬بنويسید که از ‪ Comm‬به جای ‪ awk‬برای مقايسه داده‌های جديد و قديمي استفاده کند‪.‬‬

‫تمرين ‪ .۵-۱۲‬نسخه‌ای ‪ Watchwho‬بنويسید که خروجي ‪ who‬را به جای فايلها‪ ،‬در متغیرهای پوسته ذخیره کند‪ .‬کدام نسخه را ترجیح‬


‫محیط برنامه سازی لینوکس‬

‫‪141/322‬‬

‫مي‌دهید؟ کدامیك سريعتر اجرا مي‌شود؟ آيا ‪ Watchwho‬و ‪ ، Checkmail‬بايد & را به صورت خودکار انجام دهند؟‬

‫تمرين ‪ .۵-۱۳‬چه تفاوتي میان دستور ‪ do-nothing‬و کارکتر ‪ #‬درپوسته وجود دارد؟ آيا هر دو مورد نیاز هستند؟‬

‫‪ Trap   .22126 ۵­۴‬ها‪ ،‬وقفه‌هاي جاذب‬ ‫اگرـ ‪ DEL‬را فشار دهید يا هنگام اجرایـ ‪ ، watchwho‬گوشي تلفن را بگذاريد‪ ،‬يك يا دو فايل موقت‪ ،‬درـ ‪ / tmp‬باقي مي‌ماند‪.‬‬

‫‪ Watchwho‬بايد آنها را قبل از خروج حذف کند و بايد راهي برای رويايي چنین حالتي و بازيافت آنها‪ ،‬بیابیم‪.‬‬

‫هنگامي که ‪ DEL‬را تايپ مي‌کنید‪ ،‬يك سیگنال وقفه به تمام پردازشهای در حال اجرا در ترمینال‪ ،‬ارسال مي‌شود‪ .‬مشابهاً‪ ،‬هنگامي که‬ ‫گوشي را مي‌گذاريد يك سیگنال ‪ hang up‬فرستاده مي‌شود‪ .‬سیگنالهای ديگری نیز وجود دارند‪ .‬اگر برنامه‌ای‪ ،‬عملي واضح را در مورد‬

‫سیگنالها به کار نبندد‪ ،‬سیگنال آنرا به اتمام مي‌رساند‪ .‬پوسته برنامه‌هايي که با & اجرا مي شوند را از وقفه‌ها محافظت مي‌کند اما از تعلیق‬ ‫نه‪.‬‬

‫فصل هفتم سیگنالها را مفصل به بحث مي‌گذارد‪ ،‬اما نیازی به شناختن زياد آنها برای به کار بستنشان در پوسته نیست‪.‬‬ ‫فرمان دروني پوسته ‪ ، Trap‬رشته‌ای از دستورها را هنگامي که سیگنال واقع مي‌شود‪ ،‬جهت اجرا مي‌چیند‪:‬‬

‫فهرستي از شماره‌های سیگنال‬

‫رشته‌ای از دستورات ‪trap‬‬

‫رشته‌اي از دستورات‪ ،‬آرگوماني منفرد است‪ ،‬از اين رو بايد تقريباً هميشه داخل كوتيشن قرار گيرد‪.‬‬ ‫شماره‌هاي سيگنال‪ ،‬ارقام كوچكی هستند كه سيگنال را معرفي مي‌كنند‪ .‬براي مثال‪ ۲ ،‬سيگنالي‬ ‫است كه بواسطة فشردن كليد ‪ DEL‬بوجود مي‌آيد‪ .‬و ‪ ۱‬بواسطة گذاشتن گوشي‪‌ ،‬بيشتر شماره‌هاي‬ ‫سيگنال مفيد براي برنامه‌نويسان پوسته در جدول ‪ ۵-۴‬آمده‌اند‪.‬‬

‫جدول ‪ ۵-۴‬شماره‌های سیگنال پوسته‬ ‫خروج از پوسته (به هر دلیلي‪ ،‬از جمله پايان فايل)‬

‫معلق شدن‬

‫وقفه (کلید ‪) DEL‬‬

‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪9‬‬ ‫‪19‬‬

‫خروج ( ‪ Ctl-1‬باعث مي‌شود برنامه انباری موقتي در هسته ايجاد کند)‬

‫ازبین بردن (قابل صرف نظر پا گرفتن نیست)‬

‫اتمام ‪ ،‬پیغام پیش فرضي که توسط (‪ Kill )1‬ايجاد مي‌شود‪.‬‬

‫از اين رو جهت پاك کردن فايلهای موقتي در ‪ ،watchwho‬يك فراخواني ‪ trap‬بايد دقیقا ً پیش از حلقه انجام گیرد‪ ،‬تا تعلیق‪ ،‬وقفه و‬ ‫اتمام را به دست گرفت‪:‬‬

‫‪...‬‬ ‫‪trap ' rm -f $new $ old ; exit 1' 1 2 15‬‬ ‫‪while :‬‬


‫محیط برنامه سازی لینوکس‬

‫‪142/322‬‬

‫‪...‬‬ ‫رشته دستوری که اولین آرگومان را برای ‪ Trap‬شکل مي‌دهد‪ ،‬مانند فراخواني يك زير روال است که بلفاصله هنگامي که سیگنال واقع‬ ‫مي‌شود‪ ،‬رخ مي‌دهد‪ .‬هنگامي که به اتمام رسید‪،‬برنامه‌ای که در حال اجرا بوده‪ ،‬همانجايي که بوده را از سر مي‌گیرد‪ ،‬مگر اين که سیگنال‬

‫آنرا از بین ببرد‪ .‬بنابراين ‪ ،‬رشته دستوری ‪ ‌، trap‬بايد صراحت ًا ‪ exit‬را احضار کند‪ ،‬يا برنامه پوسته اجرا را پس از وقفه‪ ‌،‬ادامه خواهد داد‪.‬‬

‫همچنین رشته دستوری‪ ،‬دوباره خوانده خواهد شد‪ :‬يکبار هنگام مقدار دهي ‪ trap‬و يکبار هنگام احضار آن‪ .‬از اين رو رشتة‌ دستوری به‬ ‫بهترين نحو با کوتیشن محافظت شده‪ ،‬متغیرها فقط هنگام اجرای روال‌های ‪ Trap‬ارزيابي مي‌شوند که در اين حالت هیچ تفاوتي‬

‫نمي‌کند اما به يك مورد بر خواهیم خورد که تفاوت خواهد داشت‪ .‬به هر حال‪ ،‬گزينة ‪ - f‬به ‪ rm‬مي‌گويد که سؤالي نپرسد‪.‬‬

‫‪ Trap‬گاهي از نظر تبادلي مفید مي‌باشد‪ ،‬اغلب جهت جلوگیری از بین رفتن يك برنامه بوسیله سیگنال تعلیق ايجاد شده توسط يك‬ ‫تلفن شکسته‪:‬‬

‫& ( ‪$ ) trap ' ' 1; long-running- command‬‬ ‫‪2134‬‬ ‫‪$‬‬

‫رشتة دستوری خنثي به معنای « صرف نظر از وقفه‌ها » در اين فرآيند مي‌باشد‪ .‬پرانتزها باعث اجرای همزمان ‪ trap‬و دستور در يك‬ ‫زير پوستة ‌زمینه مي‌شود؛ بدون آنها ‪ trap‬برای پوسته ‪‌ ، login‬همانند ‪ long-ranning-comman‬به کار بسته خواهد شد‪.‬‬

‫فرمان (‪ nohup )1‬برنامه‌ای کوتاه از پوسته است جهت جلوگیری از اين عمل‪.‬‬ ‫در اينجا نسخه ويرايش هفتم آمده شده است‪:‬‬

‫` ‪$ cat `which nohup‬‬ ‫‪trap '' '' 1 15‬‬ ‫‪if test -t 2> &1‬‬ ‫‪then‬‬ ‫'' ' ‪echo '' sending output to ' nohup . out‬‬ ‫‪exec nice -5 $ * >>nohup.out 2>&1‬‬ ‫‪else‬‬ ‫‪exec nice -5 $ * 2>&1‬‬ ‫‪fi‬‬ ‫‪$‬‬

‫‪ Test-t‬امتحان مي‌کند که خروجي استاندارد‪ ،‬يك ترمینال است‪ ،‬تا آنرا ذخیره کند‪ .‬برنامة زمینه‪ ،‬بوسیله ‪ nice‬اجرا مي‌شود تا اولويتي‬ ‫پايینتر از برنامه های تبادلي به آن دهد‪(‌ .‬توجه داشته باشید که ‪ nohup‬به ‪ ‍PATH‬مقدار دهي نمي‌کند‪ .‬آيا بايد بدهد؟)‬

‫‪ exec‬فقط برای کارآيي است؛ دستور به تنهايي و بدون آن نیز به خوبي اجرا مي‌شود‪ exec .‬دستوری دروني از پوسته است که فرآيند‬

‫در حال اجرا در اين پوسته با برنامه‌ای که نام آن آورده مي‌شود‪ ،‬عوض مي‌کند‪ ،‬بدين وسیله يك فرآيند را ذخیره مي نمايد ـ پوسته‌ای‬

‫که در حالت عادی منتظر مي‌ماند تا برنامه تکمیل شود‪ .‬مي‌توانستیم از ‪ exec‬در جاهای مختلفي استفاده کنیم‪ ،‬مانند انتهای برنامه ‪cal‬‬

‫ارتقاء يافته‪ ،‬هنگامي که ‪ / usr/bin/bin‬را احضار مي‌کند‪.‬‬

‫سیگنال ‪ ، ۹‬سیگنالي است که نمي‌توان آن را صرف نظر کرد يا بدست گرفت‪ :‬همواره از بین مي‌رود‪ ،‬از پوسته ‪ ،‬بدين گونه ارسال‬


‫محیط برنامه سازی لینوکس‬

‫‪143/322‬‬

‫مي‌شود‪:‬‬

‫‪ . . .‬عنوان فرآيند‬

‫‪$ Kill – 9‬‬

‫‪kill -9 is not the default becaise a process killed that way is given no chance to put its affairs in order‬‬ ‫‪before dying.‬‬ ‫پیش فرض نیست ‪Kill-a‬‬

‫تمرين ‪ . ۵-۱۴‬نسخه باليي ‪ ، nohup‬خطای استاندارد دستور را با خروجي استاندارد ترکیب مي‌کند‪ .‬آيا اين طرح‪ ،‬مناسب است؟ اگر‬ ‫نه‪ ،‬چگونه آن رابه خوبي از هم جدا مي‌کنید؟‬

‫تمرين ‪ . ۵-۱۵‬دستور درون پوستة ‪ times‬را پیدا کنید و به ‪ profile‬خود خطي اضافه کنید به گونه‌ای که هر گاه از پوسته خارج شويد‪،‬‬ ‫مدت زمان استفاده شما از ‪ CPU‬چاپ شود‪.‬‬

‫تمرين ‪ . ۵-۱۶‬برنامه ای بنويسید که مشخصات کاربر قابل دسترس بعدی رادر ‪ etc/passwd‬پیدا کند‪ .‬اگر مشتاق هستید ( واجازه‬ ‫داريد)‪ ،‬آنرا به دستوری اعمال کنید که کاربری جديد را به سیستم اضافه کند ‪ .‬چه مجوزهايي نیاز دارد؟ چگونه بايد با وقفه‌ها برخورد‬

‫کند؟‬

‫‪ .۵­۵‬جايگزين كردن يك فايل ‪Over write‬‬

‫دستور ‪ ، command‬داراي يك گزينة ‪ - 0‬است جهت بازنويسي يك فايل‬ ‫‪sort file1 – 0 file2 $‬‬ ‫معادل است با‬

‫‪sort file > file2 $‬‬ ‫اگر ‪ file1‬و ‪ file2‬معادل باشند‪ ،‬دوباره جهت دهي بوسیلة >‪ ،‬فايل ورودی را قبل از مرتب کردن‪ ،‬ناقص مي‌کند‪ .‬اما گزينه ‪ ، - 0‬درست‬ ‫کار مي کند‪ ،‬چرا که ورودی در يك فايل موقت‪ ،‬مرتب و ذخیره شده است‪ ،‬پیش از اينکه فايل خروجي بوجود آيد‪.‬‬

‫بسیاری دستورات ديگر قادر به استفاده از گزينه ‪ - 0‬مي باشند‪ .‬برای مثال‪ sed ،‬مي‌تواند فايلي را درجای خود ويرايش کند‪:‬‬ ‫عمل نمي کند !‬

‫‪$ sed 'S/UNIX/UNIX(TM)/g' Ch2-O Ch2‬‬

‫تعريف چنین دستورهايي جهت افزودن گزينه‪ ،‬غیر عملي خواهد بود‪ .‬علوه بر اينکه‪ ،‬طرحي بد خواهد بود‪ :‬بهتر است که توابع را هم‬ ‫مرکز کنیم‪ ،‬همانگونه که پوسته با عملگر > انجام مي‌دهد‪ .‬برای اين کار‪ Overwrite ،‬را برای برنامه به کار مي‌بريم‪ .‬اولین طرح مشابه‬ ‫زير است‪:‬‬

‫‪sed 's / UNIX/UNIX)TM( / g' ch2 | overwrite ch2 $‬‬

‫اين اشارة ابتدايي‪ ،‬قابل فهم است – فقط ورودی را تا انتهای فايل جايي ذخیره کنید و سپس داده‌ها را روی فايل آرگومان ذخیره کنید‪:‬‬

‫‪# overwrite : copy standard input to output aftert EOF‬‬ ‫‪# version 1. BUG here‬‬ ‫‪PATH= /bin:/usr/bin‬‬ ‫‪case $# in‬‬ ‫(‪1‬‬ ‫;;‬ ‫( •‬ ‫;‪echo 'Usage : overwrite file' 1>&2‬‬ ‫‪exit 2‬‬ ‫‪esac‬‬ ‫‪new= /tmp/overwr . $$‬‬ ‫‪trap ' rm -f $ new ; exit 1' 1 2 15‬‬


‫محیط برنامه سازی لینوکس‬

‫‪144/322‬‬

‫‪cat > $new‬‬ ‫‪# collect the input‬‬ ‫‪cp $ new $1‬‬ ‫‪# overwrite the input file‬‬ ‫‪rm -f $ new‬‬ ‫‪ ، Cp‬به جای ‪ mV‬استفاده مي‌شود تا مجوزها و مالك‌های فايل خروجي‪ ،‬در صورت وجود آن‪ ،‬تغییر نکنند‪ .‬همانگونه که به سادگي از‬ ‫اين نسخه بر مي‌آيد‪ ،‬دارای يك نقص مضر است‪ :‬اگر کاربر ‪ DEL‬را در حین ‪ CP‬تايپ کند‪ ،‬فايل ورودی اصلي‪ ،‬ازبین خواهد رفت‪.‬‬ ‫بايد از وقوع وقفه حاصل از متوقف ساختن بازنويسي فايل ورودی‪ ،‬جلوگیری کنیم‪:‬‬

‫‪# overwrite : copy standard input to output sfdter EOF‬‬ ‫‪# version 2. BUG here too‬‬ ‫‪PATH=/bin : /usr/bin‬‬ ‫‪case $# in‬‬ ‫(‪1‬‬ ‫;;‬ ‫( •‬ ‫‪echo `Usage : overwrite file ' 1>&2; exit 2‬‬ ‫‪esac‬‬ ‫‪new= /tmp/overwr 1.$$‬‬ ‫‪old=/tmp/overwr2 .$$‬‬ ‫‪trap 'rm -f $new $old; exit 1' 1 2 15‬‬ ‫‪cat >$new‬‬ ‫‪#collect the input‬‬ ‫‪cp $1 $old‬‬ ‫‪# save original file‬‬ ‫‪trap ' ' 1 2 15‬‬ ‫‪# we are committed; ignore signals‬‬ ‫‪cp $new $1‬‬ ‫‪# overwrite the input file‬‬ ‫‪rm -f $new $old‬‬

‫اگر پیش از دستیابي به فايل اصلي‪ ،‬يك ‪ DEL‬رخ مي‌دهد‪ ،‬فايلهای موقتي حذف شده و فايل تنها رها مي‌شود‪ .‬پس از ساختن پشتیبان‪،‬‬

‫سیگنالها صرف نظر مي‌شوند بطوريکه ‪ CP‬با وقفه‪ ،‬متوقف نمي‌گردد ـ هنگامي که ‪ CP‬شروع شود‪ Overwrite ،‬مجبور به تغییر فايل‬ ‫اصلي مي‌شود‪.‬‬

‫هنوز يك مسئله ريز وجود دارد‪ .‬توجه کنید‪:‬‬

‫‪$ sed 's/UNIX/UNIX)TM(g' percious | overwrite precious‬‬ ‫‪command garbled : s/UNIX/UNIX)TM( g‬‬ ‫‪$ 1s -1 precious‬‬ ‫‪-rw-rw-rw- 1you‬‬ ‫‪0 oct 1 09:02 precious‬‬ ‫!*@‪# $%‬‬ ‫‪$‬‬

‫اگر برنامه‌ای که ورودی را برای ‪ Overwrite‬مهیا مي‌کند‪ ،‬دچار اشتباه شود‪ ،‬خروجي آن خالي خواهد بود و ‪ Overwrite‬بنا به وظیفه و‬

‫به لحاظ اطمینان‪ ،‬فايل آرگومان را از بین مي‌برد‪.‬‬

‫چند راه حل ممکن به نظر مي رسد‪ Overwrite .‬پیش از جابجايي فايل‪ ،‬منتظر تأيید مي‌تواند باشد‪ ،‬اما تبادلي کردن آن‪ ،‬شايستگي آن را‬

‫مي‌کاهد‪ Overwrie .‬مي‌تواند بررسي کند که ورودی فايل خالي نباشد (بوسیلة ‪ ) Test-z‬اما اين کار نیز صحیح نیست‪ :‬چند خروجي‬

‫ممکن است ايجاد شود پیش از آنکه خطا رديابي شود‪.‬‬

‫بهترين راه حل ‪ ،‬اجرای برنامة تولید داده‪ ،‬تحت کنترل ‪ Overwrite‬است تا حالت خروج آن قابل بررسي باشد‪ ،‬که خلف روال مرسوم‬


‫محیط برنامه سازی لینوکس‬

145/322

:‫ بي سابقه نیست‬،‫ هیچ کلیاتي از بین نمي رود و متن آن‬،‫ با اين حال‬،‫ ايجاد نمي‌کند‬،‫ هیچ چیزی در خروجي خود‬Overwrite ،‫است‬

.‫ همگي دستوراتي هستند که دستور ديگری را به عنوان آرگومان مي پذيرند‬nohup ‫ و‬time ، nice :‫نسخة صحیح در اينجا آمده است‬

# Overwrite : copy standard input to output after EOF # final version opath=$ PATH PATH=/bin:/usr/bin case $# in 0 | 1 ( echo `Usage: overwrite file cmd ]args[' 1>&2; exit 2 esac file=$1; shift new=/tmp/overwr 1 . $$; old=/tmp/overwr2.$$ trap 'rm -f $new $old; $old; exit 1' 1 2 15 # clean up fikes if PATH=$opath ''$@'' >$new # collect input then cp $file $old # save original file trap ' ' 1 2 15 # we are committed; ignore signals cp $ new $file else echo ''overwite : $1 failed ,$ fild unchanged'' 1>&2 exit 1 fi rm -f $new $old

@ $" .‫ و غیره‬$2 ‫ مي‌شود‬$3 . $1 ‫ مي‌شود‬$2 :‫ کل فهرست آرگومان را يکي به چپ منتقل مي‌کند‬، Shift ‫فرمان درون پوسته‌ای‬

.‫ دوباره به آن خواهیم پرداخت‬5-7 ‫ در بخش‬.‫ اما وقفه نمي‌پذيرد‬،‫ تأمین مي‌کند‬،$*‫ مانند‬،)‫" تمامي آرگومانها را (پس از انتقال‬

،‫ نبودند‬usr/bin/ ‫ يا‬bin/ ‫ دستوراتي که در‬،‫ برای اجرای دستورات کاربر بازخواني مي‌شود؛ اگر چنین نبود‬PATH ‫توجه داشته باشید که‬ Overwrite now works )if somewhat clumsily(: $ cat notice UNIX is a Trademark of Bell laboratories $ overwrite notice sed 's/UNIXUNIX)TM( /g' notice command garbled: s/ UNIXUNIX)TM(/g overwrite : sed failed, notice unchanged $ cat notice UNIX is a Trademark of Bell Laboratories $ overwrit notice sed 's /UNIX/UNIX)TM(/g' notice $ cat notice UNIX )TM( is a Trademark of Bell Laboratorise $

.‫ غیر قابل دسترس مي بودند‬Overwrite ‫برای‬

‫اکنون عمل مي کند‬

Unehanged


‫محیط برنامه سازی لینوکس‬

‫‪146/322‬‬

‫استفاده از ‪ Sed‬برای جابجايي تمام رخدادهای يك کلمه‪ ،‬با يکي ديگر‪ ،‬عملکردی معمولي است‪ .‬با داشتن ‪ ،Overwrite‬خودکار کردن‬

‫اين وظیفه آسان است‪:‬‬

‫‪$ cat replace‬‬ ‫‪# replace: replace str1 in files with str2, in place‬‬ ‫‪PATH = /bin:/usr/bin‬‬ ‫‪case $# in‬‬ ‫‪0 | 1 | 2 ( echo ' Usage: replace str1 str2 files ' 1>&2; exit 1‬‬ ‫‪esac‬‬ ‫‪left = '' $1 '' ; right = ''$2''; shift; shift‬‬ ‫‪for i‬‬ ‫‪do‬‬ ‫‪overwite $i sed ''s@$ Left@$right@g'' $i‬‬ ‫‪done‬‬ ‫‪$ cat footnote‬‬ ‫‪UNIX is not an acronym‬‬ ‫‪$ replace UNIX Unix footnote‬‬ ‫‪$ cat footnote‬‬ ‫‪Unix is not an acronym‬‬ ‫‪$‬‬

‫( به خاطر بیاوريد که اگر فهرست در يك عبارت ‪ for‬خالي باشد‪ ،‬پیش فرض آن* ‪ $‬مي‌شود‪ ).‬ما از @ به جای ‪ /‬برای محدود کردن‬ ‫دستور جابجايي استفاده کرديم‪ ،‬چرا که @ کمتر با يك رشتة ورودی اشتباه گرفته مي‬

‫‪22126‬شود‪.‬‬

‫‪ replace ، PATH‬را از ‪ bin:/ust/bin/‬مقدار دهي مي‌کند‪.‬‬

‫اين بدان معني است که ‪ Ovewrite‬بايد برای عمل کردن ‪ ، replace‬در ‪ usr/bin /‬باشد‪ .‬اين فرض را برای ساده شدن کار در نظر‬ ‫گرفتیم‪ .‬اگر نمي‌توانید ‪ overwrite‬را در ‪ usr / bin /‬نصب کنید‪ ،‬مجبور به گذاشتن ‪ HOME/bin $‬در ‪ PATH‬درون ‪ replace‬هستید‬

‫يا نام مسیر ‪ overwrite‬را صراحت ًا وارد کنید‪ .‬از اين به بعد فرض مي کنیم‪.‬‬

‫تمرين‪ . ۵-۱۷‬چراـ ‪ ، overwrite‬از کد سیگنالـ ‪ O‬درـ ‪ trap‬استفاده نمي‌کند که فايلها هنگام خروج‪ ،‬حذف شوند؟ راهنمايي‪ :‬هنگام‬ ‫اجرای برنامه زير‪ DEL ،‬را تايپ کنید‪:‬‬

‫‪trap '' echo exiting; exit 1'' 0 2‬‬ ‫‪Sleep 10‬‬

‫‪ . ۵-۱۸‬يكـ ـگزينه ـ ‪ -V‬راـ ـبه ـ ‪ replace‬اضافهـ ـکنیدـ ـتاـ ـتماميـ ـخطوطـ ـتغییرـ ـيافتهـ ـدر ـ ‪ deu/tty/‬راچاپـ ـکند‪ .‬راهنمايي‪:‬‬ ‫‪S/$/sedt/$right/gsuflog‬‬ ‫‪ Replace . ۵-۱۹‬را به گونه‌ای تنظیم کنید که بدون توجه به کاراکترها در جابجايي رشته‌ها عمل کند ‪.‬‬

‫‪ . ۵-۲۰‬آيا ‪ replace‬را مي‌توان برای عوض کردن متغیر ‪ i‬با ‪ index‬در هر کجای برنامه استفاده کرد؟ برای انجام چنین موردی‪ ،‬چه‬ ‫چیزهايي را مي‌توانید تغییر دهید؟‬

‫‪ . ۵-۲۱‬آيا ‪ replace‬به مقدار کافي توانمند مي باشد که به ‪ usr/bin/‬تعلق داشته باشد‪ .‬آيا وارد کردن دستورات ‪ ، sed‬هنگام نیاز‪ ،‬ساده‬


‫محیط برنامه سازی لینوکس‬

‫‪147/322‬‬

‫مي‌باشد؟‬

‫‪( . ۵-۲۲‬مشكل) ‪$ overwrite file ′who | sort ′‬‬ ‫عمل نمي‌کند‪ .‬توضیح دهید چرا و آنها را تصحیح کنید‪ .‬راهنمايي‪ eval)1(:‬را در(‪ sh )1‬ببینید‪ .‬راه حل شما‪ ،‬چگونه بر تفسیر‬ ‫متاکاراکترها در دستور تأثیر مي‌گذارد‪.‬‬

‫‪ :  Zap  .۵.۶‬از بين بردن فرآيند ‪ ،‬از روي نام‬ ‫دستور ‪ kil‬فقط فرآيندهايي رابه پايان مي رساند که بوسیلة شناسة فرآيند‪ ،‬معرفي شده باشند‪ .‬هنگامي که يك فرآيند زمینة خاص ‪ ،‬لزم‬

‫به از بین رفتن است‪‌،‬معمولً بايد ‪ PS‬را برای يافتن شناسة فرآيند اجرا کرد و سپس به دشواری آنرا مانند يك آرگومان دوباره وارد کرد‬

‫تا از بین روند‪ .‬اما وارد کردن برنامه برای چاپ عددی که فورا ً آنرا بطور دستي رونويسي مي‌کنید‪ ،‬چندان عاقلنه نیست‪ .‬چرا برنامه‌ای‬ ‫ننويسیم‪ ،‬مثلً با ‪ say‬که اين کار را خودکار انجام دهد؟‬

‫يك دلیل اين است که فرآيندهای از بین برنده‪ ،‬خطرناك مي باشند و بايد مراقب بود که فرآيند صحیح از بین برود‪ .‬يك روش سالم و‬ ‫مناسب‪ ،‬اجرا کردن ‪ ZAP‬است بصورت تبادلي ‪ ،‬و استفاده از ‪ Pick‬برای انتخاب قرباني‌ها‪.‬‬

‫يك يادآوری سريع دربارة ‪ :Pick‬هر کدام از آرگومانهای خود را به نوبت چاپ کرده و از کاربر پاسخ مي‌خواهد؛ اگر پاسخ ‪ y‬باشد‪،‬‬ ‫آرگومان چاپ مي گردد‪ Pick( .‬موضوع بخش بعدی است)‬

‫‪ ZAP‬از ‪ Pick‬استفاده مي‌کنند تا صحت فرآيندهايي را که از روی نامشان توسط کاربر‪ ،‬برای از بین رفتن انتخاب شده‌اند را بررسي‬ ‫کند‪.‬‬

‫‪$ cat zap‬‬ ‫‪# zap pattetn: kill all ptocesses matching pattern‬‬ ‫‪# BUG in this vetsion‬‬ ‫‪PATH=/bin : /usr/bin‬‬ ‫‪cas $# in‬‬ ‫(‪0‬‬ ‫‪ecvgo 'Usage: zap pattern' 1>&2; exit 1‬‬ ‫‪esac‬‬ ‫` ' {!‪kill `pick \ `ps – sg | frep '' $* ''\ ` | awk ' }print $‬‬ ‫‪$‬‬

‫‪ .1‬به علمتهای ` که توسط ‪ backslash‬ها احاطه شده اند‪ ،‬توجه کنید‪ .‬برنامة ‪ ، awk‬شناسه فرايند را از خروجي ‪ PS‬که بوسیلة ‪Pick‬‬ ‫انتخاب شده‌‪ ،‬بر مي‌گزيند‪:‬‬

‫& ‪4 sleep 1000‬‬ ‫‪22126‬‬ ‫‪$ ps – ag‬‬ ‫‪PID TTY TIME CMD‬‬ ‫‪...‬‬ ‫‪22126 0 0:00 slepp 1000‬‬ ‫‪...‬‬ ‫‪$ zap sleep‬‬ ‫?‪22126‬‬


‫محیط برنامه سازی لینوکس‬

‫‪148/322‬‬

‫چه اتفاقي مي افتد؟‬

‫‪0? q‬‬

‫مسأله اين است که خروجي ‪ PS‬به کلماتي بخش بخش شده که بوسیلة ‪ Pick‬به عنوان آرگومانهای مجزا ديده مي‌شوند‪ ،‬به جای اينکه‬

‫کل خط يك باره پردازش شود‪.‬‬

‫رفتار عادی پوسته‪ ،‬شکستن رشته‌ها به آرگومانهايي است فاصله دار و بدون فاصله‪ ،‬مانند‪:‬‬

‫‪For i in 1 2 3 4 5‬‬ ‫در اين برنامه بايد تقسیمات پوسته را بر روی رشته‌ها‪ ،‬به آرگومانها‪ ،‬کنترل کنیم‪ ،‬تا فقط خطوط جديد‪ ،‬کلمات کنار هم را از هم جدا‬

‫کنند‪.‬‬

‫متغیر پوسته ‪( IFS‬جدا کنندة میدان داخلي) ‪ ،‬رشته‌ايست از کاراکترها که کلمات را در فهرست آرگومانها‪ ،‬از هم جدا مي‌کند‪ ،‬مانند ` و‬

‫جملت ‪ . for‬به طور معمول ‪ ، IFS ،‬شامل يك جای خالي‪ ،‬يك پرش و يك خط جديد مي باشد اما مي‌توانیم آنرا به هر چیزمفیدی‬ ‫تبديل کنیم‪ ،‬مانند يك خط جديد‪:‬‬

‫‪$ echo ' echo $# ' >nargs‬‬ ‫‪$ cx naegs‬‬ ‫‪$ who‬‬ ‫‪you‬‬ ‫‪tty0‬‬ ‫‪0ct 1 05:59‬‬ ‫‪pjw‬‬ ‫‪tty2‬‬ ‫‪oct‬‬ ‫‪1 11:26‬‬ ‫`‪$ nargs `who‬‬ ‫‪10‬‬ ‫میدانهای مجزای ده خط و يك خط جديد‬ ‫' = ‪$ IFS‬‬ ‫فقط يك خط جديد‬

‫'‬ ‫دو خط جديد‪ .‬دو میدان‬

‫`‪$ nargs `who‬‬ ‫‪2‬‬

‫‪$‬‬ ‫‪:‬به خوبي کار مي‌کند ‪، zap‬توسط خط جديد ‪ IFS‬با مقدار دهي‬

‫‪$ cat zap‬‬ ‫‪# zap pat: kill all procsses matching pat‬‬ ‫‪# final version‬‬ ‫‪22126‬‬ ‫‪PATH= /bin :/usr/bin‬‬ ‫'=‪IFS‬‬ ‫'‬ ‫‪# just a newline‬‬ ‫‪case $ 1 in‬‬ ‫( '' ''‬ ‫;; ‪echo 'Usage: zap ]-2[ pattern' 1>&2; exit 1‬‬ ‫(* –‬ ‫‪SIG= $1 ; shift‬‬ ‫‪esac‬‬ ‫' ‪esac‬‬ ‫‪PID TTY‬‬ ‫'‪TIME CMD‬‬ ‫` ' {‪kill $SIG ` pick \` ps -ag | egrep '' $ * ''\` | awk '}print $1‬‬ ‫‪$ ps – ag‬‬ ‫‪PID TTY TIME CMD‬‬ ‫‪...‬‬ ‫‪22126 0 0:00 sleep 1000‬‬


‫محیط برنامه سازی لینوکس‬

‫‪149/322‬‬

‫‪...‬‬ ‫‪$ zap sleep‬‬ ‫‪PID TTY TIME CMD‬‬ ‫‪22126 0 0:00 sleep 1000? y‬‬ ‫‪23104 0 0:02 egrep sleep? n‬‬ ‫‪$‬‬

‫ما دو چين خوردگي را وارد كرديم‪ :‬يك آرگومان اختياري براي مشخص كردن سيگنال (توجه‬ ‫كنيد كه ‪ SIG‬معرفي نشده مي‌ماند و از اين رو‪ ،‬به عنوان يك رشتة بي تأثير تلقي خواهد‬ ‫شد‪ ،‬اگر آرگومان به كار گرفته نشود) و استفاده از ‪ egrep‬به جاي ‪ ، grep‬براي مجاز كردن‬ ‫نمونه‌هاي پيچيده‌تر مانند ‪ .Sleep | date′ ′‬يك ‪ echo‬ابتدايي‪ ،‬سرصفحه‌هاي ستوني را براي‬ ‫خروجي ‪ Ps‬به چاپ مي رساند‪.‬‬

‫حتما ً تعجب خواهید کرد چرا اين فرمان به جای فقط ‪ zap ، kill‬خوانده مي‌شود‪ .‬دلیل اصلي اين است که برخلف مثال ما در مورد‬ ‫‪ ، cal‬در حقیقت فرمان ‪ Kill‬جديدی ايجاد نمي‌کنیم‪ ZAP :‬الزاما ً تبادلي است‪ ،‬به يك دلیل ‪ -‬و ما مي‌خواهیم ‪ Kill‬را به همین دلیل‬

‫نگهداريم‪ Zap .‬همچنین به طرز آزار دهنده‌ای کند است ‪ -‬هزينه تمام برنامه‌های اضافي‪ ،‬قابل قبول است‪ ،‬با وجود آنکه ‪( Ps‬که بايد به‬ ‫هر صورتي اجرا شود) گرانترين است‪.‬‬

‫در فصل بعد‪ ،‬کارکردی مؤثر تر از ارائه خواهیم داد‪.‬‬

‫تمرين‪ ZAP . ۵-۲۳‬را بگونه‌ای تعريف کنید که سرصفحة ‪ PS‬را از ‪ pipeline‬چاپ کند بطوريکه به تغییرات درساختار خروجي ‪، Ps‬‬ ‫حساس نباشد‪ .‬اين تغییر ‪ ،‬تا چه حد برنامه را پیچیده مي‌کند؟‬

‫‪ ۵­۷‬ـ دستور ‪ :  Pick‬جاهاي خالي آرگومانها‬ ‫ما تقريبا ً با هر آنچه برای نوشتن دستور ‪ pick‬در پوسته نیاز داريم‪‌،‬بر خورد داشته‌ايم‪ .‬تنها چیز جديدی که نیاز است‪ ،‬مکانیزمي است‬ ‫برای خواندن ورودی کاربر‪ .‬دستور داخلي پوسته ‪ ، read‬يك خط از متن را از ورودی استاندارد خوانده و متن را به عنوان مقدار متغیر‬

‫نام برده مي خواند (بدون خط جديد)‪.‬‬

‫‪$ read greeting‬‬ ‫‪. hello , world‬وارد کنید ‪ greeting‬مقداری جديد برای‬

‫‪$ echo $ greeting‬‬ ‫‪hello , world‬‬ ‫‪$‬‬ ‫معمول‌ترين استفاده ‪ read‬در ‪ .profile‬است جهت تنظیم محیط‪ ،‬هنگام ورود به سیستم تا متغیرهای پوسته مقدار دهي اولیه شوند‪ ،‬مانند‬

‫‪.TERM‬‬ ‫‪ Read‬فقط مي‌تواند از ورودی استاندارد بخواند؛ حتي قابل جهت دهي مجدد نیز نیست‪ .‬هیچ يك از دستورات درون پوسته (برخلف‬ ‫اصول اولیه کنترل جريان مانند ‪ ) for‬قابل جهت دهي مجدد با > يا < نیستند‪.‬‬

‫‪$ read greeting </etc/passwd‬‬


‫محیط برنامه سازی لینوکس‬

‫‪150/322‬‬

‫بايد مقداری وارد شود‬

‫اکنون پوسته گزارش خطا مي‌دهد‬

‫مقداری را وارد کرده ‪ ،‬نه از فايل ‪Greeting‬‬

‫‪goodbye‬‬ ‫‪illegal io‬‬ ‫‪$ echo $greeting‬‬ ‫‪goodbye‬‬ ‫‪$‬‬

‫اين امر را مي‌توان به عنوان نقصي در پوسته قلمداد کرد‪ ،‬اما واقعیت دارد‪ .‬خوشبختانه مي توان با دوباره جهت دادن حلقه محاط بر ‪for‬‬ ‫اين موضوع را نیز حل کرد‪ .‬اين کلید مشکل ما در به کار بردن دستور ‪ pick‬است‪:‬‬

‫‪# pick: select arguments‬‬ ‫‪PATH= /bin:/usr/bin‬‬ ‫‪for i‬‬ ‫‪# for each argument‬‬ ‫‪do‬‬ ‫‪echo -n ''$i? '' >/dev/tty‬‬ ‫‪read response‬‬ ‫‪case $response in‬‬ ‫(*‪y‬‬ ‫;; ‪echo $i‬‬ ‫(*‪q‬‬ ‫‪break‬‬ ‫‪esac‬‬ ‫‪done </dev/tty‬‬

‫‪ echo-n‬آخرين خط جديد را متوقف مي‌کند‪ ،‬تا پاسخ در آن‪ ،‬به صورت يك پیغام فوری‪ ،‬قابل تايپ شدن باشد‪ .‬و البته پیغامهای فوری‬ ‫در ‪ dev/tty/‬چاپ مي‌شوند‪ ،‬چرا که خروجي استاندارد اغلب مطمئناً ترمینال نیست‪.‬‬

‫جملة ‪ break‬از ‪ C :‬قرض گرفته شده است‪ :‬حلقة دروني احاطه شده را پايان مي‌دهد‪ .‬در اين حالت‪ ،‬حلقة ‪ For‬را هنگامي که ‪ q‬تايپ‬

‫شود‪ ،‬قطع مي‌کند‪ .‬اجازه مي‌دهیم ‪ q‬انتخاب را به پايان برساند چرا که انجام آن آسان است‪ ‌ ،‬ذاتا ً بي زحمت و با ساير برنامه‌ها نیز‬ ‫سازگار است‪.‬‬

‫برای اجرای ‪ ، Pick‬استفاده از جاهای خالي در آرگومانها‪ ،‬جالب به نظر مي رسد‪:‬‬

‫‪$ pick ' 1 2 ' 3‬‬ ‫?‪1 2‬‬ ‫?‪3‬‬

‫اگر مايلید بدانید ‪ Pick‬چگونه آرگومانهای خود را انتخاب مي کند‪ ،‬آنرا اجرا کرده و فقط پس از هر پیغام فوری‪ Return ،‬را فشار‬

‫دهید‪ .‬همانگونه که انتظار مي‌رود‪ ،‬درست عمل مي‌کند‪ For i :‬آرگومانها را درست جابجا مي‌کند‪ .‬مي‌توانستیم حلقه را به روشهای‬

‫ديگری بنويسیم‪:‬‬

‫‪see what this version does‬‬

‫‪$ grep for pick‬‬ ‫* ‪for i in $‬‬ ‫‪$ pick '1 2' 3‬‬ ‫?‪1‬‬ ‫?‪2‬‬ ‫?‪3‬‬


‫محیط برنامه سازی لینوکس‬

‫‪151/322‬‬

‫‪$‬‬ ‫اين فرم جواب نمي‌دهد‪ ،‬زيرا عملگرهای حلقه دوباره جاروب مي‌شوندو جاهای خالي در اولین آرگومان‪ ،‬باعث مي‌شود به دو آرگومان‬

‫تبديل شوند‪ .‬اين بار باگذاشتن " برای* ‪ $‬امتحان کنید‪.‬‬

‫نسخه ای ديگر را امتحان کنید‬

‫‪$ grep for pick‬‬ ‫''*‪for i in ''$‬‬ ‫‪$ pick ' 1 2 ' 3‬‬ ‫?‪1 2 3‬‬ ‫‪$‬‬

‫اين يکي نیز کار نمي‌کند‪ ،‬چرا که ˝ * ‪ ˝ $‬کلمه‌ايست مفرد و متشکل از تمامي آرگومانهايي که به يکديگر پیوسته اند و با جای خالي از‬ ‫هم جدا شده‌اند‪.‬‬

‫البته راه حلي وجود دارد‪ ،‬اما تقريباً شعبده بازی است‪ :‬رشتة ˝ @ ‪ ، ˝ $‬توسط پوسته‪ ،‬به طور ويژه‌ای مورد توجه قرار مي‌گیرد و دقیقاً‬

‫به آرگومانهای فايل پوسته تبديل مي‌شود‪:‬‬

‫نسخه سوم را امتحان کنید‬

‫‪$ grep for pick‬‬ ‫''@‪for i in ''$‬‬ ‫‪$ pick ' 1 2 ' 3‬‬ ‫?‪1 2‬‬ ‫?‪3‬‬ ‫‪$‬‬

‫اگر @ ‪ $‬داخل کوتیشن قرار نگرفته باشد‪ ،‬همانند * ‪ $‬تلقي مي‌گردد؛ رفتار فقط هنگامي مخصوص خواهد بود که داخل ˝ قرار گیرد‪،‬‬ ‫از آن در ‪ Overwrite‬برای نگه‌داشتن آرگومانها برای دستور کاربر استفاده کرديم‪.‬‬

‫به طور خلصه‪ ،‬قوانیني در اينجا ذکر مي‌گردند‪:‬‬

‫•*‪ $‬و @‪ ، $‬به آرگومانها توسعه داده و دوباره جاروب مي شوند؛ جاهای خالي در آرگومانها‪ ،‬آرگومانهای متعددی را نتیجه خواهد‬ ‫داد‪.‬‬

‫• ''*‪ ''$‬کلمه ايست منفرد‪ ،‬مرکب از تمامي آرگومانهای موجود در پوسته که با فاصله هايي به يکديگر متصل شده اند‪.‬‬

‫•* ''@‪ ''$‬مشابه آرگومانهايي است که بوسیله فايل پوسته دريافت مي گردند‪ :‬جای خالي در آرگومانها ناديده گرفته مي‌شوند و‬ ‫نتیجه‪ ‌،‬فهرستي است از کلماتي که يکسان با آرگومانهای اصلي هستند‪.‬‬

‫اگر ‪ Pick‬آرگوماني نداشته باشد‪ ،‬بايد ورودی استاندارد خود را بخواند‪ ،‬از اين رو مي‌توان از‪:‬‬

‫> ‪< mailing list‬‬

‫‪$ Pick‬‬ ‫به جای‬

‫` ‪$ Pick ̀Cat mailing list‬‬ ‫استفاده کرد‪ .‬اما ما اين نسخه از ‪ Pick‬را مورد بررسي قرار نمي‌دهیم‪ :‬با پیچیدگي‌های ناهنجاری همراه است و بسیار مشکل‌تر از برنامة‬ ‫مشابهي است که با ‪ C‬نوشته مي‌شود‪ ،‬که در فصل بعد آنرا بحث خواهیم کرد‪.‬‬

‫دو تمرين اول پیش رو مشکل مي‌باشند‪ ،‬اما برای برنامه‌نويسان پیشرفته پوسته ‪ ،‬آموزنده‌اند‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪152/322‬‬

‫ما دو چین خوردگي را وارد کرديم‪ :‬يك آرگومان اختیاری برای مشخص کردن سیگنال (توجه کنید که ‪ SIG‬معرفي نشده مي‌ماند و از‬

‫اين رو‪ ،‬به عنوان يك رشتة بي‌تأثیر تلقي خواهد شد‪ ،‬اگر آرگومان به کار گرفته نشود) و استفاه ازـ ‪ egrep‬به جایـ ‪ ، grep‬برای‬ ‫مجازکردن نمونه‌های پیچیده‌تر مانند '‪ . 'sleep | date‬يك ‪ echo‬ابتدايي‪ ،‬سرصفحه‌های ستوني را برای خروجي ‪ ps‬به چاپ مي‌رساند‪.‬‬

‫تمرين ‪ . ۵-۲۴‬سعي کنید با ‪ pick‬برنامه‌ای بنويسید که آرگومانهايش را از ورودی استاندارد بخواند‪ ،‬اگر هیچ کدام در خط فرمان عرضه‬ ‫نشده باشند‪ .‬بايد جاهای خالي را به خوبي کنترل کند‪ .‬آيا ‪ q‬کار مي کند؟ اگرنه‪ ،‬تمرين بعدی را امتحان کنید‪.‬‬

‫تمرين ‪ . ۵ -۲۵‬با وجود اينکه دستورات دروني پوسته مانند ‪ read‬و ‪ set‬قابل جهت دهي مجدد نیستند‪ ،‬خود پوسته‪ ،‬موقتا ً قابل جهت‬ ‫دهي است‪ .‬بخش مربوط به (‪ sh)1‬را که ‪ enec‬را توصیف کرده و چگونگي خواندن از ‪ ، dev/tty‬را بدون فراخواني يك زير پوسته‪،‬‬

‫کامل تشريح مي‌کند‪ ( .‬ممکن است خواندن فصل ‪۷‬بتواند کمك کند‪) .‬‬

‫تمرين ‪(. ۵ -۲۶‬بسیار ساده‌تر) ‪ read‬را در ‪ . protile‬خود بخوانید و ‪ TERM‬و هرآنچه به آن بستگي دارد را بنويسید‪.‬‬

‫‪ . ۵­۸‬دستور ‪ : news‬پيغامهاي خدمات اجتماعي‬ ‫در فصل اول‪ ،‬اشاره کرديم که سیستم شما ممکن است دارای يك فرمان ‪ news‬جهت گزارش پیغامهای عمومي جامعة کاربر باشد‪.‬‬ ‫باوجود اينکه نام و جزيیات دستور تفاوت دارند‪ ،‬اکثر سیستمها‪ ،‬دارای يك سرويس خبری است‪ .‬دلیل ما برای ارائة فرما ن ‪news‬‬

‫جايگزين کردن دستور محلي شما نیست بلکه برای اينست که نشان دهیم به چه سادگي چنین برنامه‌ای را در پوسته‪ ،‬مي‌توان نوشت‪.‬‬

‫مقايسة دستور ‪ news‬ما با ويرايش محلي شما‪ ،‬مي‌تواند جالب باشد‪.‬‬

‫ايدة ابتدايي چنین برنامه‌ای‪ ،‬اين است که مقالت خبری‪ ،‬هرکدام در يك فايل‪ ،‬در يك دايرکتوری ويژه مانندـ ‪ usr/news/‬ذخیره‬

‫مي‌شوند‪(news .‬برنامة ‪ )،news‬ازمقايسة زمانهای تعريف فالها در ‪ usr/news/‬با همان نمونه‌ها در دايرکتوری شما (‪). news-time‬‬

‫عمل مي‌کند‪.‬‬

‫مي‌توانیم از « ‪ » .‬به عنوان دايرکتوری برای هم فايلهای خبری و هم ‪ . news-time‬استفاده کنیم; که هنگام آماده بودن برای اشکال‬

‫زدايي‪،‬برنامه جهت استفاده عمومي‪ ،‬قابل تغییر به ‪ usr/news/‬مي‌باشد‪.‬‬

‫‪$ cat news‬‬ ‫‪# news: print news files, vrsion 1‬‬ ‫‪HOME=.‬‬ ‫‪# debugging only‬‬ ‫‪cd .‬‬ ‫‪# place holder for /usr/news‬‬ ‫` ‪for i in `1s -t * $ HOME/ . news – time‬‬ ‫‪do‬‬ ‫‪case $i in‬‬ ‫(‪• / .news – time‬‬ ‫;; ‪break‬‬ ‫( •‬ ‫‪echo news: $i‬‬ ‫‪• 22126‬‬ ‫‪esac‬‬ ‫‪done‬‬ ‫‪touch $HOME/ . news – time‬‬ ‫‪$ touch x‬‬ ‫‪$ touch y‬‬


‫محیط برنامه سازی لینوکس‬

‫‪153/322‬‬

‫‪$ news‬‬ ‫‪news : y‬‬ ‫‪news : x‬‬ ‫‪$‬‬ ‫‪ touch‬زمان آخرين تغییر فايل آرگومان خود را به زمان حال تغییر مي‌دهد‪ ،‬بدون تغییری در فايل‪ ،‬برای عیب يابي‪ ،‬فقط اسامي فايلهای‬ ‫خبری را بازگشت مي‌دهیم‪ ،‬به جای اينکه آنها را چاپ کنیم‪.‬‬

‫حلقه وقتي پايان مي‌يابد که ‪ . news-time‬را بیابد‪ ،‬از آن به بعد‪ ،‬تنها آنهايي را فهرست مي‌کند که جديدتر باشند‪ .‬دقت کنید که * در‬

‫جملت ‪ ،case‬مي‌تواند با يك ‪ /‬مطابقت داشته باشد‪.‬‬

‫چه اتفاقي مي‌افتد اگر ‪ . newd-time‬وجود نداشته باشد؟‬

‫‪$ rm .news – time‬‬ ‫‪4 news‬‬ ‫‪$‬‬

‫اين سکوت‪ ،‬غیر منتظره است و اشتباه ‪ ،‬اما رخ مي‌دهد چرا که اگر ‪ LS‬نتواند فايلي را بیابد‪ ،‬در خروجي استاندارد خود‪ ،‬پیش از چاپ‬

‫هر اطلعاتي دربارة فايلهای موجود‪ ،‬وجود مشکلي را گزارش مي‌دهد‪ .‬اين يك عیب بوده اما ما مي‌توانیم آنرا با تشخیص مشکل در‬ ‫حلقه‪ ،‬حل کنیم و خطای استاندارد را به خروجي استاندارد دوباره جهت دهیم‪( .‬اين شکل درنسخه‌های جديدتر سیستم حل شده بود‪) .‬‬

‫‪$ cat news‬‬ ‫‪# news: print news files, version 2‬‬ ‫‪HOME= .‬‬ ‫‪# debugging only‬‬ ‫‪cd .‬‬ ‫‪# place holder for / usr/news‬‬ ‫' = ‪IFS‬‬ ‫'‬ ‫‪# just a newline‬‬ ‫`‪for i in ` 1s – t * $ HOME/ .news – time 2>&1‬‬ ‫‪do‬‬ ‫‪case $i in‬‬ ‫( ' ‪• ' not found‬‬ ‫;;‬ ‫( ‪• / .news – time‬‬ ‫;; ‪break‬‬ ‫( •‬ ‫;; ‪echo news : $i‬‬ ‫‪esac‬‬ ‫‪done‬‬ ‫‪touch $ HOME/ .news – time‬‬ ‫‪$ rm .news – time‬‬ ‫‪$ news‬‬ ‫‪news : news‬‬ ‫‪news: y‬‬ ‫‪news: x‬‬ ‫‪$‬‬

‫بايد ‪ IFS‬را از خط جديد مقدار دهي کنیم تا پیغام‬ ‫به سه کلمه تجزيه نشود‪.‬‬

‫‪./.news-time no found‬‬


‫محیط برنامه سازی لینوکس‬

‫‪154/322‬‬

‫در قدم بعدی‪ news ،‬بايد فايلهای خبری را چاپ کند‪ ،‬به جای آنکه نام آنها را برگرداند‪ .‬اين کار از اين بابت مفید است که مي‌توان‬

‫فهمید چه کسي و چه زماني را ارسال نموده‪ ،‬و از اين رو از دستور ‪ set‬و ‪ LS-1‬برای چاپ يك سرصفحه قبل از خود پیغام‪ ،‬استفاده‬ ‫مي‌کنیم‪:‬‬

‫‪news‬‬

‫‪208 o ct 1 12:05‬‬

‫اشتباهي رخ داده است !‬

‫‪$ 1s -1 news‬‬ ‫‪– r wxrwxrwx 1 you‬‬ ‫` ‪$ set `1s -1 news‬‬ ‫(‪- rwxrwxrwx: bad optin)S‬‬ ‫–‬

‫‪$‬‬

‫اينجا‪،‬ت تمثالي تاست تازت تجايي تكهت تقابليت تجابجايي تبرنامه‌ها توت تداده‌هات تدرت تپوسته‪،‬ت تمورد‬ ‫استفاده قرار مي‌گيرد‪.‬‬

‫‪ Set‬اعتراض مي‌كند‪ ،‬چرا كه آرگومان آن ("‪ )"rwnrwxrwx-‬باعلمت منفي شروع شده و مانند‬ ‫يك گزينه ببه نظر مي‌آيد‪ .‬يك راه حل ساده (اگر باهوش باشيد)‪ ،‬افزودن يك پيش وند است‬ ‫به آرگومان مانند يك كاركتر عادي‪:‬‬ ‫` ‪$ set X ` 1s -1 news‬‬ ‫'' ‪$ echo ''news: )$3( $5 $6 $7‬‬ ‫‪news: )you( oct 1 12:05‬‬ ‫‪$‬‬ ‫اين يك غالب قابل قبول است و نويسنده و تاريخ پیغام را همراه با نام فايل نشان مي‌دهد‪.‬‬ ‫در اينجا آخرين ويرايش دستور ‪ news‬آمده است‪:‬‬

‫‪# news: print news files , final version‬‬ ‫‪PATH= /bin:/usr/bin‬‬ ‫' =‪IFS‬‬ ‫'‬ ‫‪# just a newline‬‬ ‫‪cd/ usr/news‬‬ ‫`‪for i in `1s - t * $ HOME/ .news – time 2>&1‬‬ ‫‪do‬‬ ‫' ' =‪IFS‬‬ ‫‪case $i in‬‬ ‫;; ( ' ‪• ' not found‬‬ ‫;; ‪• /.news – time( break‬‬ ‫( •‬ ‫`‪set X` 1s -1 $i‬‬ ‫'' ‪echo‬‬ ‫‪$i : )$3( $5 $6 $7‬‬ ‫‪cat $i‬‬ ‫‪esac‬‬ ‫‪done‬‬ ‫‪touch $HOME/ . news - time‬‬


‫محیط برنامه سازی لینوکس‬

‫‪155/322‬‬

‫خطوط جديد اضافي در سرصفحه‪ ،‬مقالت خبری را در حین چاپ از هم جدا مي‌کنند‪ .‬اولین مقدار ‪ ، IFS‬فقط يك خط جديد است‪،‬‬ ‫از اين رو پیغام ‪( not faund‬اگر باشد) از اولین ‪‌، LS‬به عنوان يك آرگومان منفرد تلقي مي‌گردد‪ .‬دومین وظیفة ‪ ،IFS‬آنرا دوباره جای‬ ‫خالي مقدار دهي مي‌کند‪ ،‬از اين رو خروجي دومین ‪ ،LS‬به آرگومان هايي تجزيه مي‌‌کند‪.‬‬

‫تمرين‪ . ۵-۲۷‬يك گزينه ‪ -n‬را به ‪ news‬اضافه کنید تا مقالت خبری را گزارش دهد اما چاپ نکند و به ‪ . news – time‬دست نیابد‪.‬‬ ‫ممکن است در ‪ . profile‬شما جای گیرد‪.‬‬

‫‪ . ۵-۲۸‬طرح‪ ،‬و کارکرد ‪ news‬در دستورات مشابه روی سیستم خود را با يکديگر مقايسه کنید‪.‬‬

‫‪ get  .۵­۹‬و ‪ : put‬رديابي تغييرات فايل‬ ‫در اين بخش‪ ‌،‬تا آخرين بخش يك فصل طولني ‪ ،‬يك مثال بزرگتر و پیچیده‌تر را به بحث مي‌گذاريم که همکاری پوسته را با ‪sed ,‬‬

‫‪ ، awk‬تشريح مي‌کند‪.‬‬

‫يك برنامه‪ ،‬با درست کردن معايب و اضافه کردن ويژگیها‪ ،‬تکامل مي‌يابد‪ .‬گاهي رديابي اين ويرايشها‪ ،‬به ويژه هنگامي که افراد برنامه را‬

‫برای ساير ماشینها به کار مي‌برند‪ ،‬ساده مي‌نمايد ـ برمي‌گردند سئوال مي‌کنند « از وقتي که ويرايش ما نصب شده‪ ،‬چه تغییری حاصل‬

‫شده؟ » يا « اين عیب يا آن مشکل را چگونه برطرف کرديد؟ » همچنین‪ ،‬همواره نگهداشتن نسخه‌های پشتیبان‪ ،‬تجربه کردن ايده‌ها را‬ ‫بي‌آسیب تر مي‌کند‪ :‬اگر چیزی کار نمي‌کند‪ ،‬بازگشتن به برنامه اصلي‪ ،‬بدون دردسر خواهد بود‪ .‬يك راه حل‪ ،‬نگه داشتن کپي‌های تمام‬

‫ويرايشهاست‪ ،‬اما اين کار با زحمت و هزينة زيادی همراه است‪ .‬درعوض‪ ،‬بر روی نسخه‌هايي متمرکز مي‌شويم که دارای بسیاری‬

‫قسمتهای مشترك بوده و يکبار نیاز به ذخیره شدن دارند‪.‬‬

‫دستور‬

‫‪diff - e old new‬‬

‫‪$‬‬

‫فهرستي از دستورات ‪ ed‬را که ‪ old‬را به ‪ new‬تبديل مي‌کنند‪ ،‬ايجاد مي‌کند‪ ،‬از اين رو نگهداشتن تمامي نسخه‌های يك فايل در يك‬ ‫فايل جداگانه (متفاوت) با نگهداری يك نسخة کامل و مجموعه‌ای از دستورات ويرايشي برای تبديل آن به هر نسخه‪ ،‬میسر مي‌شود‪.‬‬

‫دو نوع سازماندهي وجود دارد‪ :‬جديدترين ويرايش را در دسترس نگه داشته و دستورات ويرايشي را عقب برد و يا قديمي‌ترين‬

‫ويرايش ها را نگه داشت و دستورات ويرايشي را جلو برد‪ .‬باوجود اينکه دومي برای برنامه نويسي ساده‌تر است‪ ،‬اولي سريعتر است اگر‬

‫ويرايشهای زيادی در دسترس باشد‪ .‬ما سازماندهي اول را انتخاب مي‌کنیم‪ .‬در يك فايل منفرد که آنرا فايل تاريخچه نام گذاری مي‌کنیم‪،‬‬ ‫ويرايش جاری و در پي آن مجموعه‌ای از دستورات ويرايشي که هر ويرايشي را به ويرايش قبلي برمي‌گرداند‪ ،‬موجود مي باشند‪.‬‬

‫هرمجموعه از دستورات ويرايشي‪ ،‬با خطي شروع مي‌شوند مشابه‬

‫خلصه‬

‫تاريخ‬

‫شخص‬

‫@@@‬

‫خلصه‪ ،‬خطي است منفرد‪ ،‬که بوسیله شخص تأمین شده و تغییر را توصیف مي‌نمايد‪ .‬برای نگهداری از نسخه‌ها‪ ،‬دو دستور وجود‬

‫دارد‪ get :‬ويرايشي را از فايل تاريخچه گرفته و ‪ put‬نسخه‌ای جديد را به آن وارد مي‌نمايد‪ ،‬پس از اينکه يك خط خلصة تغییرات‬

‫درخواست شود‪.‬‬

‫پیش از نشان دادن کاربرد‪ ،‬مثالي در اينجا برای بیان چگونگي عمل ‪ get‬و ‪ put‬و فايل تاريخچه چگونه نگهداری مي‌شود‪ ،‬آورده شده‪:‬‬


‫محیط برنامه سازی لینوکس‬

156/322

$ echo a line of text >junk $ put junk Summary: make a new file get: no file junk . H put: creating junk . H

‫توصیفات را وارد نمايید‬

..... ‫تاريخچه موجود نمي‌باشد‬ ‫ آنرا ايجاد مي‌کند‬put ......

$ cat junk . H a line of text @@@ you sat oct 1 13:31:03 EDT 1983 make a new file $ echo another line >> junk $ put junk summary: one line added $ line of text another line @@@ you sat oct 1 13:32:28 EDT 1983 one line added 2d @@@ you sat oct 1 13:31:03 EDT 1983 make a new file $ .‫ ويرايش جديد را به نسخة اصلي برمي‌گرداند‬،‫ که خط دوم فايل را از بین مي‌برند‬2d ‫« دستورات ويرايشي » شامل خط منفرد‬

$ rm junk $ get junk

$ cat junk a line of text another line $ get -1 junk $ cat junk a link of text $ get junk

‫جديدترين ويرايش‬

‫ويرايش يکي مانده به آخر‬ ‫جديدترين ويرايش دوباره‬

$ reolace antother 'a different ' junk $ put junk summary: second line changed $ cat junk . H a line of text a different line @@@ you sat oct 1 13:34:07 EDT 1983 second line changed 2c another line . @@@ you sat oct 1 13:32:28 EDT 1983 one line added 2d @@@ you sat oct 1 13:31:03 EDT 1983 make a new file $


‫محیط برنامه سازی لینوکس‬

‫‪157/322‬‬

‫دستورات ويرايشي‪ ،‬از بال تا پايین سراسر فايل تاريخچه‪ ،‬اجرا شده تا ويرايش دلخواه را استخراج کنند‪ :‬سری اول‪ ،‬جديدترين را به‬

‫دومین نسخة جديد تبديل مي‌کند‪ ،‬بعدی آن را به سومین نسخة جديد برمي‌گرداند و … از اين رو‪ ،‬درواقع فايل جديد را هر بار با‬

‫اجرای ‪ ed‬يکي‪ ،‬به نسخة قديمي برمي‌گردانیم‪.‬‬

‫اگر فايلي را که با @@@ آغاز شده باشد را مورد اصلح قرار دهیم‪ ،‬قطعا ً به مشکل برخواهیم خورد و بخش عیب‌ها از (‪،diff)1‬‬ ‫درباره خطوطي که شامل فقط يك دوره مي‌شوند‪ ،‬اخطار خواهد داد‪ .‬ازـ @@@ برای علمت گذاری دستورات ويرايشي استفاده‬

‫مي‌کنیم‪ ،‬چرا که رشته‌ايست ناخواسته برای متني معمولي‪.‬‬

‫باوجود آنکه نشان دادن چگونگي تکامل دستورات ‪ get‬و ‪ ، put‬مي‌تواند مفید واقع شود‪ ،‬اما طولني بوده و نشان دادن فرم‌های گوناگون‬ ‫آنها‪ ،‬مستلزم بحث زيادی است‪ .‬از اين جهت تنها فرمهای نهايي آنها را به شما نشان مي‌دهیم‪ Put .‬ساده‌تر است‪:‬‬

‫‪# put: install file in to history‬‬ ‫‪PATH=/bin: / usr / bin‬‬ ‫‪case $# in‬‬ ‫(‪1‬‬ ‫;; ‪HIST=$1 . H‬‬ ‫(‪2‬‬ ‫;; ‪echo ' Usage: put fill ' 1>&2; exit 1‬‬ ‫‪esac‬‬ ‫‪if test ! -r $1‬‬ ‫‪then‬‬ ‫‪echo ''put: can ' t open $1'' 1>&2‬‬ ‫‪exit 1‬‬ ‫‪fi‬‬ ‫‪trap 'rm -f /tmp/put . ]ab[$$; exit 1' 1 2 15‬‬ ‫' ‪echo -n ' Summary:‬‬ ‫‪read Summary‬‬ ‫‪if get -o /tmp/put.a$$ $1‬‬ ‫‪# previous versoin‬‬ ‫‪then‬‬ ‫‪# merge pieces‬‬ ‫‪cp $ 1 /tmp/put.b$$‬‬ ‫‪# current versin‬‬ ‫‪echo ''@@@ ` getname ` `date` $Summary '' >>/tmp/put.b$$‬‬ ‫‪diff -e $1 /tmp/put.a$$ >>/tmp/put.b$$ # Latest diffs‬‬ ‫‪sed -n '/^@@@/, $p' <$HIST >>/tmp/put.b$$ # old diffs‬‬ ‫‪overwrite $HIST cat /tmp/put.b$$‬‬ ‫‪# put it back‬‬ ‫‪else‬‬ ‫‪# mske a new one‬‬ ‫''‪echo ''put: creating $HIST‬‬ ‫‪cp $1 $HIST‬‬ ‫‪echo ''@@@ `getname ` ` date` $Summary'' >> $HIST‬‬ ‫‪fi‬‬ ‫‪rm -f /tmp/put.]ab[$$‬‬

‫بعد از خواندن خلصة يك خطي‪ put ger ،‬را جهت استخراج ويرايش قبلي فايل از فايل تاريخچه ‪ ،‬فراخواني مي‌کند‪ .‬گزينة ‪ ، -o‬يك‬

‫فايل خروجي متبادل را به ‪ get‬اختصاص مي‌دهد‪ .‬اگر ‪ get‬نتوانست فايل تاريخچه را بیابد‪ ،‬يك پیغام خطا برگردانده و ‪ put‬يك فايل‬

‫تاريخچه جديد ايجاد مي‌کند‪ .‬اگر فايل تاريخچه وجود داشته باشد‪ ،‬عبارت ‪ ، then‬تاريخچه جديد را در يك فايل موقت‪ ،‬به ترتیب از‬ ‫آخرين ويرايش‪ ،‬خط @@@ دستورات ويرايشگر‪ ،‬برای تبديل از جديدترين ويرايش قبلي‪ ،‬ايجاد مي‌کند‪ .‬سرانجام‪ ،‬فايل موقت روی‬


‫محیط برنامه سازی لینوکس‬

158/322

.‫ کپي مي‌شود‬overwrite ‫ با استفاده از‬،‫فايل‬

.‫ است که بیشتر به خاطر داشتن گزينه‌هاست‬put ‫ پیچیده‌تر از‬get

# get: extract file from history PATH=/bin:/usr/bin VERSION=0 while test ''$1'' ! = '' '' do case ''$1'' in -i ( INPUT=$2; shift ;; -o ( OUTPUT=$2; shift ;; -]0-9[ ( VERSION = $1 ;; – * ( echo ''get: Unknown srgument $i'' 1>&2; exit 1 ;; • ( case ''$OUTPUT'' in '' '' ( OUTPUT = $1 ;; • ( INPUT = $1.H ;; esac esac shift done OUTPUT= $ }OUTPUT? ''Usage: get ]- o outfile[ ]-i file . H[ file ''{ INPUT = $ } INPUT - $OUTPUT.H { test -r $ INPUT | | } echo ''get: no file $ INPUT'' 1>&2; exit 1; { trap 'rm -f /tmp/get.]ab[ $$; exit 1' 1 2 15 # split into current version and editing commands sed < $ INPUT -n ' 1 ,/^@@@/w /tmp/get.a'$$' /^@@@/ ,$w /tmp/get.b'$$ # perform the edits awk </tmp/get.b$$ ' /^@@@/ } count ++ { !/^@@@/ && count > 0 && count < = '$VERSION' END } print ''$d''; print ''w'' , '' ' $OUTPUT ' '' { ' | ed - /tmp/get.a$$ rm -f /tmp/get.]ab[ $$ ‫ ويرايشي خاص را انتخاب‬، - ]0-9[ .‫ ورودی و خروجي را مشخص مي‌کنند‬، - O ‫ – و‬i .‫ کامل ً عادی و معمولي مي‌باشند‬،‫گزينه‌ها‬ ‫ است با يك‬while ،‫ يکي مانده به جديدترين و … حلقة شامل آرگومانها‬-1 ، )‫ جديدترين ويرايش است (پیش فرض‬O :‫مي‌نمايد‬ ‫ داد و‬shift ‫ ) از يك آرگومان ديگر نیز استفاده کرده و بايد آنرا‬- i ‫ – و‬O( ‫ چرا که برخي گزينه‌ها‬،‫ مي‌باشد‬for ‫ به جای‬shift ‫ و‬test

‫ شمارش کارکتر را که‬، ed » - « ‫ گزينة‬.‫ با هم به درستي کار نمي‌کنند‬،‫ باشد‬for ‫ داخل حلقه‬shift ‫ اگر‬،‫ها‬shift ‫ و‬for ‫اينکه حلقه‌های‬

.‫معمولً به همراه خواندن يا نوشتن يك فايل اجرا مي‌شود را متوقف مي‌کند‬

‫خط‬ test -r $INPUT | | } echo '' get: no file $INPUT'' 1>&2; exit 1; { ‫معادل است با‬:


‫محیط برنامه سازی لینوکس‬

‫‪159/322‬‬

‫‪if test ! -r $INPUT‬‬ ‫‪then‬‬ ‫‪echo ''get: no file $ INPUT'' 1>&2‬‬ ‫‪exit 1‬‬ ‫‪fi‬‬ ‫(که همان فرمي است که برای ‪ put‬استفاده نموديم) اما کوتاهتر و برای برنامه‌نويساني که با عملگر ـ | | آشنا هستند‪ ،‬واضح‌ترا ست‪.‬‬ ‫دستورهای بین {‪ ، },‬در پوستة جاری اجرا مي‌شوند‪ ،‬دريك زير پوسته؛ اين امر الزامي است چرا که ‪ exit‬از ‪ get‬خارج مي شود و نه‬

‫فقط از يك زيرپوسته‪ .‬کارکترهای {‪ },‬مانند ‪ do‬و ‪ done‬مي‌باشند ـ اگر بعد از آنها‪ ،‬يك « ; » يا خط جديد يا هر پايان دهندة دستور‪،‬‬ ‫دارای معني خاصي است‪.‬‬

‫سرانجام سراغ کد واقع در ‪ get‬که اين کار را انجام مي‌دهد مي‌آيیم‪ .‬درابتدا‪ sed ،‬فايل تاريخچه را به دو قسمت تقسیم مي‌کند‪ :‬آخرين‬

‫نسخه و مجموعة ويرايش‌ها‪ .‬سپس برنامة ‪ ،awk‬فرامین ويرايشي را پردازش مي‌کند‪ .‬خطوط @@@ ‪ ،‬شمرده (و نه چاپ) مي‌شوند و‬ ‫آنجايي که شمارش‪ ،‬بیشتر از ويرايش موردنظر نباشد‪ ،‬دستورهای ويرايشي‪ ،‬عبور مي‌کنند (به خاطر بیاوريد که عملکرد پیش فرض‬

‫‪ ،awk‬چاپ کردن خط ورودی است)‪ .‬دو دستور ‪ ed‬پس از آن از فايل تاريخچة اضافه مي‌شوند‪ ، $d :‬خط @@@ را ‪ ، sed‬آنرا در‬

‫ويرايش جديد‪ ،‬رها مي‌کند‪ ،‬حذف مي‌نمايد ويك دستورـ ‪ ، W‬فايل را در موقعیت نهايي خود‪ ،‬مي‌نويسد‪ Overwrite .‬در اينجا‬

‫غیرالزامي مي‌نمايد‪ ،‬چرا که ‪ get‬تنها ويرايش فايل را تغییر مي‌دهد و نه فايل ارزشمند تاريخچه را‪.‬‬

‫تمرين ‪ . ۵-۲۹‬يك ‪ version‬دستوری بنويسید که دو کار انجام دهد‪:‬‬

‫‪version -5 file $‬‬ ‫خلصه‪ ،‬تاريخ تغییر و شخصي که تغییر ويرايش انتخاب شده را در فايل تاريخچه انجام دهد‪:‬‬ ‫‪version sep 20 file $‬‬

‫گزارش دهد که کدام شماره ويرايش در ‪ ۲۰‬سپتامبر جاری بوده‪‌،‬که نوعا در‬

‫‪`get `version sep 20 file $‬‬

‫مورد استفاده قرارمي‌گیرد‪ version( .‬مي‌تواند نام فايل تاريخچه را برای سادگي کار برگرداند‪).‬‬

‫تمرين ‪ get . ۵-۳۰‬و ‪ put‬را طوری تعريف کنید که فايل تاريخچه را دريك دايرکتوری جداگانه‪ ،‬به خوبي به کار بندد ‪ .‬به جای اينکه‬ ‫دايرکتوری در حال کار را با فايلهای ‪ .H‬شلوغ کند‪.‬‬

‫‪ . ۵-۳۱‬تمامي ويرايش‌های يك فايل‪ ،‬پس از سامان گرفتن همه چیز‪ ،‬ارزش حفظ کردن ندارند‪ .‬چگونه مي‌توانید ترتیبي اتخاذ کنید که‬ ‫ويرايشهايي را از میان فايل تاريخچه حذف کنید‪.‬‬

‫‪ ۵­۱۰‬نگاهي به آنچه گذشت‬ ‫هنگامي که بانوشن يك برنامه مواجه مي‌شويد‪ ،‬تمايلي طبیعي به شروع به فکر کردن به اين موضوع وجود دارد که آنرا به زبان مورد‬

‫علقه خودتان بنويسید‪ .‬در اين مورد‪ ،‬آن زبان‪ ،‬پوسته است‪.‬‬

‫باوجود آنکه گاهي رسم الخطي نامأنوس دارد‪ ،‬پوسته زبان برنامه‌نويسي مناسبي مي‌باشد‪ .‬مطمئناًـ سطح آن بالست؛ عملگرهای آن‬ ‫برنامه‌هايي هستند کامل‪ .‬از آنجايیکه تبادلي مي‌باشد‪ ،‬برنامه‌ها مي‌توانند بصورت تبادلي توسعه پیدا کنند و در چند قدم و در حین کار‬


‫محیط برنامه سازی لینوکس‬

‫‪160/322‬‬

‫قابل پاليش شدن هستند‪ .‬بعد از آن‪ ،‬اگر جهت کارهايي غیرشخصي نیز نیاز باشند‪ ،‬با پرداخته و محکم کاری شدن‪ ،‬مي‌توانند جهت‬ ‫استفاده‌های متنوع‌تر آماده شوند‪ .‬در آن حالت غیرمعمولي که پوسته بايد بسیار کارآمد باشد‪ ،‬برخي ‪ ،‬يا تمام برنامه‌های آن مي‌توانند با‬ ‫‪ C‬نوشته‌شوند‪ ،‬اما باز هم با طرح دستنويس‪( .‬اين روش را در فصل بعد به بحث خواهیم گذاشت)‪.‬‬

‫در اين فصل بسیاری مثالها را که با برنامه‌ها و پوسته‌های موجود راحت قابل انجام هستند‪ ،‬آورده شده‌اند‪ .‬گاهي دوباره مرتب کردن‬

‫آرگومانها‪ ،‬کافي مي‌باشد؛ در حالتي که با ‪ cal‬کار مي‌کنیم‪ .‬گاهي پوسته حلقه‌ای بر يك مجموعه از نام فايلها يا يك توالي از اجرای‬

‫دستورات‪ ،‬ايجاد مي‌کند‪ ،‬مانند ‪ . checlcmail , watchfor‬مثالهای پیچیده‌تر‪ ،‬نسبت به ‪ ،C‬کمتر کار مي‌برند ؛ برای مثال ويرايش ‪۲۰‬‬ ‫خطي ما از ‪ ،news‬جايگزين ويرايش ‪ ۳۵۰‬خطي ‪ C‬شده است‪.‬‬

‫اما اينها برای داشتن يك زبان دستورات قابل برنامه‌ريزی‪ ،‬کافي نیست‪ .‬آنچه اهمیت دارد‪ ،‬اين است که تمامي اجزاء با هم کار کنند ‪.‬‬

‫هرکدام برای تمرکز بر روی يك کار و انجام بهینه آن طراحي شده‌اند‪ ،‬سپس پوسته آنها را هرگاه که ايده‌ای جديد داريد‪ ،‬با هم پیوند‬

‫مي‌دهد‪ ،‬به راحتي و با کارايي بال‪ ،‬همین همکاری باعث مي‌شود که محیط برنامه‌نويسي ‪ UNIX‬بسیار کارآمد باشد‪.‬‬

‫نكاتي از تاريخچه و شكل گيري‬ ‫ايدة ‪ ، put , get‬از سیسم کنترل که مرجع (‪ )sccs‬که بوسیلة ‪ Marc Rochkind‬ايجاد شده‪ ،‬مي‌آيد‪ sccs ، IEEE "( .‬ترجمه‌ای بر‬ ‫مهندسي نرم‌افزار ‪ sccs . )1975 ،‬بسیار توانمند و انعطاف پذيرتر از برنامه‌های سادة ماست؛ جهت نگهداری برنامه‌های عظیم در يك‬ ‫محیط تولیدی کاربرد دارد‪ .‬مبنای ‪ sccs‬مشابه برنامه ‪ diff‬است‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪161/322‬‬

‫فصل ششم‪ :‬مقدمه‌ای بر زبان ‪C‬‬ ‫اين بخش شامل مقدمه مختصر زبان ‪ c‬مي باشد‪ .‬قصد داشته به عنوان خود آموز زبان بوده‪ ،‬و با اين هدف که خواننده ای که ‪c‬را تازه‬

‫شروع کرده به سرعت ممکن برسد‪ .‬مطمئنا بعنوان جانشیني برای کتابهای درسي بیشمار ‪ c‬نیست‪.‬‬

‫بهترين راه آموزش يك زبان جديد انساني صحبت کردن آن درست از آغاز است‪ .‬گوش دادن و تکرار پیچیدگي های دستور زبان را از‬

‫بین مي برد‪ .‬همینطور برای زبان های کامپیوتری‪ -‬يادگیری ‪ -c‬بکار مي رود و ما بايد نوشتن برنامه های ‪ c‬را با سرعت ممکن آغاز‬

‫کنیم‪.‬‬

‫يك کتاب درسي عالي ‪ c‬نوشته شده توسط دو نويسنده شناخته شده و بسیار بزرگ‪:‬‬

‫زبان برنامه نويسي ‪ANSI C-C‬‬

‫بريان ‪ W.C‬کرينان و دنیس ‪ .M‬ريتچي‬

‫فرنتیس هال ‪۱۹۸۸‬‬

‫دنیس ريتچي اولین مترجم ‪C‬رابر روی ‪ PDP-11‬طراحي و پیاده سازی کرد(ماشین ماقبل تاريخ با استانداردهای امروزی‪ ،‬که تاکنون‬

‫تاثیر زيادی بر محاسبات علمي مدرن داشته است‪ ).‬زبان ‪ c‬بر مبنای دو زبان ( اکنون از بین رفته ) بوده‪( BCPL :‬بي سي پي ال) ؛‬

‫مارتین ريجاردز‪ ،‬و ‪( B‬بي) نوشته کن تامپسون در سال ‪ ۱۹۷۰‬برای اولین سیستم يونیکس بر روی ‪ . PDP_7‬زبان اصلي و رسمي ‪R:C‬‬ ‫و ‪ K‬بود‪ .‬که برگرفته از نام دو نويسنده زبان برنامه نويسي ‪ c‬اصلي بوده است‪ .‬در سال ‪ ۱۹۸۸‬موسسه استانداردهای ملي آمريکا (‬

‫‪ )ANSI‬نسخه جديدو اصلح شده ‪ c‬را که امروزه با عنوان (‪ ) ANSI C‬شناخته شده را پذيرفت‪.‬‬

‫اين نسخه در ويرايش جاری زبان برنامه نويسي ‪ ANSI C-C‬توصیف شده‪ .‬نسخه ‪ ANSI‬شامل اصلحیه های زياد نحوی و کارهای‬

‫دروني زبان مي باشد‪ .‬موارد مهم اصلح شده نحو فراخواني برای روالها و استاندارد سازی بیشتر کتابخانه های سیستم است ( ولي‪،‬‬

‫متاسفانه نه تمام آنها)‬

‫یک برنامه مقدماتی‬ ‫با نام خدا شروع مي کنیم‬

‫برنامه زير را در ويرايشگر مورد علقه خود تايپ کنید‪.‬‬

‫کد را در فايل ‪ hello.c‬ذخیره‪ ،‬و سپس با تايپ ‪ gcc hello.c‬آن را ترجمه (کامپايل) کنید‪.‬‬

‫اين يك فايل قابل اجرای ‪ a.out‬را بعد از اجرا بسادگي با تايپ نام آن ايجاد مي کند‪.‬‬

‫>‪# include <stdio .h‬‬ ‫( ) ‪void main‬‬ ‫}‬ ‫;(”‪print f )“\ nHello world \n‬‬ ‫{‬

‫در نتیجه کاراکترهای ‪ Hello world‬با يك خط خالي چاپ مي شود‪.‬يك برنامه ‪ c‬شامل توابع و متغیر هاست‪ .‬توابع کارهايي که توسط‬ ‫برنامه اجرا مي شوند را مشخص مي کنند‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪162/322‬‬

‫تابع «‪( »main‬اصلي) در بالی برنامه قرار مي گیرد‪ .‬بطورمعمول کوتاه بوده و توابع مختلف را برای اجرای زير – وظايف فراخوني مي‬ ‫کند‪ .‬همه کدهای ‪ c‬بايد دارای تابع ‪ main‬باشند‪.‬‬

‫کد ‪ printf ,hello.c‬را که يك تابع خروجي از کتابخانه ‪( I/O‬ورودی ‪/‬خروجي) که در فايل ‪ stdio.h‬تعريف شده) را فراخواني مي‬ ‫کند‪ .‬زبان اصلي ‪ c‬به هیچوجه دارای حکم های ‪ I/O‬توکار (دروني ) نمي باشد‪ .‬توابع رياضي زيادی نیز ندارد‪ .‬زبان اصلي واقعا به‬

‫منظور محاسبات علمي يا تکنیکي نبوده ‪ ...‬اين توابع اکنون توسط کتابخانه استاندارد اجرا مي شوند‪ ،‬که اکنون بخشي از ‪ANSI C‬‬

‫هستند‪ .‬کتاب ‪ K & R‬محتوای اينها و کتابخانه های استاندارد ديگر در ضمیمه ( پیوست ) را فهرست مي کند‪.‬‬

‫خط ‪ printf‬پیام ‪ hello word‬را بر ‪ ( stdout‬مسیر خروجي متناظر با پنجره ترمینال يا پايانه ‪ x‬در آنچه شما کد را اجرا مي کنید )‬

‫چاپ مي کند‪.‬‬

‫“‪ ”/n‬يك خط جديد چاپ نموده‪ ،‬که کرسور را به خط بعدی مي آورد‪ .‬توسط ‪ ، printf‬اين خط هرگز ايجاد نمي شود‪ .‬برنامه زير‬ ‫همین نسخه را تولید مي کند‪:‬‬

‫‪<include < stdio.h#‬‬ ‫()‪void main‬‬ ‫}‬ ‫;("‪printf)"\n‬‬ ‫;("‪printf)"Hello World‬‬ ‫;("‪printf)"\n‬‬ ‫{‬

‫سعي کنید "‪ ”\n‬را خارج کرده و نتیجه را ببینید‪.‬‬

‫اولین حکم ">‪ ”#include<stdio.h‬شامل مشخصه کتابخانه ‪ I/O‬زبان ‪ c‬است‪ .‬همه متغیرهای ‪ c‬بايد صريحا قبل از استفاده تعريف‬

‫شوند‪ .‬فايل های "‪ ”h‬فايل های سر آيند بوده که شامل تعريف متغیرها و توابع لزم برای کار کردن برنامه ها چه در بخش نوشته شده‬ ‫توسط کاربر از کدباشند‪ ،‬يا بعنوان کتابخانه های استاندارد ‪ c‬باشد‪ ،‬مي باشد‪ .‬نماد ">‪ ”<....‬مترجم را برای جستجوی فايل در کتابخانه‬ ‫های استاندارد سیستم راهنمايي مي کند‪.‬‬

‫کلمه ‪ void‬قبل از ‪ main‬مشخص مي کند که تابع ‪ main‬از نوع ‪ void‬است‪ .‬يعني هیچ نوع وابسته به آن ندارد‪ .‬به اين معنا که نمي‬

‫تواند نتیجه ای را هنگام اجرا برگرداند‪.‬‬

‫کاراکترـ ";” انتهای دستور را مشخص مي کند‪ .‬بلوکهای دستورات در آکولدـ {‪ }....‬قرار مي گیرند‪ ،‬همانند تعريف توابع‪ .‬تمام‬ ‫دستورات ‪ c‬در فرمت آزاد تعريف مي شوند‪ .‬بدون طرح بندی مشخص شده يا انتساب ستون‪ .‬فضای سفید ( تبها يا فاصله ها) معني‬

‫ندارند‪ .‬بجز درون کوتیشن ها ( نقل قول) بعنوان بخشي از رشته کاراکتری‪ .‬برنامه زير دقیقا همین نتیجه را برای مثال ما مي دهد‪:‬‬

‫دليل مرتب کردن برنامه در خطوط و نمايش ساختار واضح است‪.‬‬

‫>‪#include < stdio.h‬‬ ‫{;("‪void main)(}printf)"\nHello World\n‬‬


‫محیط برنامه سازی لینوکس‬

163/322

‫محاسبه‬ .‫ درجه محاسبه مي کند‬۳۶۰ ‫ تا‬۰ ‫ را برای زاويه های بین‬sine ‫ جدولي از توابع‬sine.c ،‫برنامه زير‬

/************************/ /* Table of */ /* Sine Function */ /************************/ /* Michel Vallieres */ /* Written: Winter 1995 */ #include < stdio.h> #include < math.h> void main)( } int angle_degree; double angle_radian, pi, value; /* Print a header */ printf )"\nCompute a table of the sine function\n\n"(; /* obtain pi once for all */ /* or just use pi = M_PI, where M_PI is defined in math.h*/

pi = 4.0*atan)1.0(; printf ) " Value of PI = %f \n\n", pi (; printf ) " angle angle_degree=0;

Sine \n" (; /* initial angle value /* scan over angle */

*/

while ) angle_degree <= 360 ( /* loop until angle_degree > 360 */ } angle_radian = pi * angle_degree/180.0 ; value = sin)angle_radian(; printf ) " %3d %f \n ", angle_degree, value (;

{

{

angle_degree = angle_degree + 10; /* increment the loop index

*/


‫محیط برنامه سازی لینوکس‬

‫‪164/322‬‬

‫کد با توضیحاتي ك هدف آن را مشخص مي کند شروع مي شود‪.‬‬

‫اين يك سبك خوب برنامه نويسي است که کار شما را مشخص و مستند مي کند‪.‬‬

‫توضیحات مي توانند هر جايي از کد نوشته شوند‪:‬هر کاراکتر بین *\ ‪ *\ ,‬توسط مترجم ناديده گرفته مي شود و فقط برای کد استفاده‬ ‫مي شود‪ .‬استفاده از نامهای متغیر با معني در متن مساله نیز نظر خوبي است‪.‬‬

‫دستور ‪ # include‬اکنون شامل فايل سر آيند برای کتابخانه رياضي استاندارد ‪ math.h‬مي باشد‪ .‬اين دستور نیاز به تعريف فراخواني‬

‫های توابع مثلثاتي ‪ atsn‬و ‪ sin‬دارد‪( .‬توجه کنید که ‪ compilation‬همچنین بايد شامل کتابخانه رياضیات دقیقا با تايپ ‪gcc sine.c‬‬

‫‪ -lm‬باشد)‪.‬‬

‫نام های متغیر دلخواه است‪ ( .‬توسط بعضي از مترجم ها طول ماکزيمم نوعا ‪ ۳.۲‬کاراکتر تعريف شده )‬

‫‪ c‬از انواع متغیرهای استاندارد زير استفاده مي کند‪.‬‬

‫‪ : int‬متغیر صحیح‬

‫‪ : short‬صحیح کوتاه‬

‫‪ :long‬صحیح طولني‬

‫‪ :float‬متغیر حقیقي‬

‫‪ : double‬متغیر حقیقي ( متغیر شناور ) دقت مضاعف‬

‫‪ :char‬متغیر کاراکتری (يك بايت )‬

‫مترجم ها سازگاری انواع همه متغیرهای استفاده شده در کد را بررسي مي کنند‪ .‬اين ويژگیها باعث جلوگیری از اشتباه مي شود‪ .‬و‬ ‫خصوصا در خطای نوع نام های متغیر‪ .‬محاسبات انجام شده در روالها در کتابخانه رياضي معمول در دقت مضاعف محاسبه شده ‪۶۴ ( .‬‬ ‫بیت در بیشتر ايستگاههای کاری ) تعداد واقعي بايتها در حافظه دروني اين انواع داده وابسته به ماشیني که استفاده شده بکار رفته است‪.‬‬

‫تابع ‪ ، printf‬مي تواند برای چاپ مقادير صحیح‪ ،‬حقیقي و رشته ها بکار رود‬ ‫نحو کلي اين است‪:‬‬

‫; (‪printf)“format” ,variable‬‬ ‫که ‪ format‬مشخصه تبديل و ‪ variable‬فهرست مقادير چاپ است‪ .‬بعضي فرمتهای مورد استفاده عبارتند از؛‬

‫‪ :%nd‬صحیح ( ‪ n‬اختیاری = تعداد ستونها ؛ اگر ‪ 0‬باشد ‪،‬با صفر پر مي شود )‬

‫‪ : %mnf‬متغیر حقیقي ساده يا مضاعف ( ‪ m‬اختیاری = تعداد ستونها و ‪ n‬تعداد ارقام اعشار )‬

‫‪ : %ns‬رشته ( ‪ n‬اختیاری = تعداد ستونها )‬

‫‪ :%c‬کاراکتر‬

‫\‪ : n\t‬برای ايجاد خط يا تب جديد‬

‫‪ : \g‬صدای زنگ ( “ بیپ" ) بر روی پايانه ( ترمینال)‬


‫محیط برنامه سازی لینوکس‬

‫‪165/322‬‬

‫‪ ­۳‬حلقه ها‪:‬‬ ‫اکثر برنامه های واقعي شامل ساختاری است که در برنامه حلقه مي زند‪ .‬اجرای عملهای مکرر در يك جريان داده يا ناحیه ای از حافظه‪.‬‬ ‫چندين روش برای حلقه در ‪ c‬وجود دارد‪ .‬دو حلقه بسیار رايج يکي ‪ while‬است‪.‬‬ ‫‪ ( while‬عبارت )‬

‫{‪ ...............‬بلوك دستورات برای اجرا ‪......‬‬ ‫}‬ ‫و ديگر حلقه ‪for‬‬

‫‪( for‬عبارت ‪ ۳‬؛ عبارت ‪ ۲‬؛ عبارت ‪)۱‬‬ ‫{‬ ‫‪ ........‬بلوك دستورات برای اجرا ‪.......‬‬ ‫}‬

‫حلقه ‪ while‬به حلقه ادامه مي دهد تا زمانیکه عبارت شرطي نادرست شود‪ .‬شرط هنگام ورود به حلقه تست مي شود‪ .‬هر ساختار‬ ‫منطقي ( فهرست زير را ببینید) مي تواند در اين زمینه استفاده شود‪.‬‬

‫حلقه ‪ for‬يك نوع خاص است و معادل است با حلقه ‪ while‬زير‪.‬‬

‫؛ عبارت ‪۱‬‬

‫‪( while‬عبارت ‪)۲‬‬

‫{‬ ‫‪ .......‬بلوك دستورات ‪........‬‬

‫؛ عبارت ‪۳‬‬

‫}‬

‫برای نمونه‪ ،‬ساختار زير اغلب مشاهده مي شود‪:‬‬

‫‪ i = i‬مقدار اولیه ;‬

‫‪ while ) i < = i‬ماکزيمم )‬ ‫{‬ ‫‪...‬بلوك دستورات ‪...‬‬ ‫‪ i = i + i‬نمو ;‬

‫}‬

‫اين ساختار با نحو آسانتر حلقه ‪ for‬بازنويسي مي شود‪:‬‬

‫‪ = for )i‬مقدار اولیه ; ‪ = >i‬حداکثر ; = ‪ i + i‬نمو‬ ‫{‬ ‫‪ ........‬بلوك دستورات ‪............‬‬ ‫}‬

‫حلقه بي نهايت نیز ممکن است ( برای مثال ( ; ; ) ‪ . ) for‬ولي برای هزينه کامپیوتر خیلي خوب نیست!‬


‫محیط برنامه سازی لینوکس‬

‫‪166/322‬‬

‫‪ c‬به شما اجازه نوشتن حلقه بي نهايت را مي دهد و دستور ‪ break‬را برای شکستن و خروج از حلقه فراهم کرده است‪.‬‬ ‫برای مثال‪ ،‬به مثال زير که بازنويسي شده حلقه قبلي است توجه کنید‪:‬‬

‫;‪angle_degree = 0‬‬ ‫( ; ; ) ‪for‬‬

‫}‬ ‫‪ .........‬بلوك دستورات ‪...........‬‬

‫;‪angle_degree = angle_degree + 10‬‬ ‫;‪if )angle_degree == 360( break‬‬ ‫{‬ ‫شرط ‪ if‬به طور ساده مي پرسد آيا ‪ angle‬ـ ‪ ( degree‬درجه زاويه ) مساوی ‪ ۳۶۰‬هست يا نه؛‬ ‫اگر هست‪ ،‬حلقه تمام شود ( بايستد)‬

‫‪ ‬ثوابت نهادی‬ ‫شما مي توانید ثابت های هر نوع را با استفاده از راهنمای مترجم ‪ # define‬تعريف کنید‪ ،‬نحو آن ساده است ‪.‬‬

‫برای نمونه‬

‫‪٫#define ANGLE_MIN 0‬‬

‫‪#define ANGLE_MAX 360‬‬ ‫‪ ANGLE_MAx,ANGLE_MIN‬را به ترتیب مقادير ‪ ۰‬و ‪ ۳۶۰‬درجه تعريف مي کند‪ C .‬بین حروف کوچك و بزرگ در نام متغیرها‬ ‫تفاوت قائل مي شود‪ .‬معمول است که از حروف بزرگ در تعريف ثابتهای سراسری استفاده شود‪.‬‬

‫‪ ‬شرطها‬ ‫شرط ها با ساختارهای ‪ if‬و ‪ while‬استفاده مي شوند‪.‬‬ ‫‪ if ) i‬شرط )‬

‫{‬ ‫‪ .............‬بلوك دستورات اجرايي اگر شرط ‪ ۱‬درست باشد ‪.........‬‬ ‫}‬ ‫‪ ( eles if‬شرط ‪) ۲‬‬

‫{‬ ‫‪ ......‬بلوك دستورات اجرايي اگر شرط ‪ ۲‬درست باشد ‪......‬‬ ‫}‬ ‫‪else‬‬ ‫{‬ ‫‪ .........‬بلوك دستورات اجرايي در غیر اينصورت ‪...........‬‬ ‫}‬


‫محیط برنامه سازی لینوکس‬

‫‪167/322‬‬

‫و مشتقات متفاوت آن‪ .‬هم با حذف شاخه ها يا شامل شرايط تو در تو‪.‬‬

‫شرط ها عملگرهای منطقي شامل مقايسه مقادير ( از يك نوع ) هستند که از عملوندهای شرطي استفاده مي کنند‪.‬‬

‫< کوچکتر از‬

‫= < کوچکتر از يا مساوی با‬ ‫= = مساوی با‬

‫= ! مساوی نیست با‬

‫= > بزرگتر از يا مساوی با‬ ‫> بزرگتر از‬

‫و عملوند های بولي‬ ‫&&‬ ‫| |‬ ‫‪not‬‬

‫و‬

‫يا‬

‫نه‬

‫کاربرد ديگر شرط در ساختار ‪ switch‬است‪.‬‬

‫‪ (switch‬عبارت )‬ ‫{‬

‫‪case‬‬

‫عبارت ثابت ‪; ۱‬‬

‫{‬ ‫‪ ..........‬بلوك دستورات ‪.........‬‬ ‫‪; break‬‬ ‫}‬ ‫عبارت ثابت ‪; ۲‬‬ ‫‪case‬‬

‫{‬ ‫‪ .........‬بلوك دستورات ‪........‬‬

‫‪; break‬‬ ‫}‬ ‫‪: default‬‬ ‫{‬ ‫‪ ..........‬بلوك دستورات ‪.........‬‬ ‫}‬ ‫}‬

‫بلوك مناسب دستورات مطابق مقدار عبارت‪ ،‬مقايسه شده توسط عبارت های ثابت در دستور ‪ case‬اجرامي شود‪ .‬دستور ‪ break‬اطمینان‬

‫مي دهد که ‪ case‬هايي ك در ادامه ‪ case‬انتخاب شده آمده اند اجرا نخواهند شد‪.‬‬

‫اگر شما مي خواهید اين دستورات را اجرا کنید‪ .‬بايد دستور ‪ break‬را رها کنید‪ .‬اين ساختار بويژه در بررسي متغیر ها ورودی کاربرد‬ ‫دارد‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪168/322‬‬

‫اشاره گرها‬ ‫زبان ‪ c‬به برنامه نويس اجازه خواندن و نوشتن در محلهای حافظه را بطور مستقیم مي دهد‪ .‬اين قابلیت انعطاف بال وقدرت زبان رانشان‬ ‫مي دهد‪ .‬البته يکي از موانع بزرگي است که برنامه نويس مبتدی بايد دراستفاده از زبان چیره شود‪.‬‬

‫همه متغیر های يك برنامه در حافظه مقیم هستند‪ .‬دستورات‬ ‫‪; float X‬‬ ‫‪x = 6.5‬‬

‫نیاز دارد که مترجم ‪ ۴‬بايت از حافظه را در يك کامپیوتر ‪ ۳۲‬بیتي برای متغیرهای ممیز شناور ‪ x‬ذخیره کند و سپس مقدار ‪ 6.5‬را درآن‬ ‫قرار دهد‪.‬‬

‫گاهي اوقات ما مي خواهیم بدانیم يك متغیر در کجاهای حافظه مقیم است‪ .‬آدرس ( مکان در حافظه ) هر متغیر با قرار دادن عملوند‬

‫"&” قبل از نام آن بدست مي آيد‪ .‬بنابراين ‪ & ampx‬آدرس ‪ x‬است‪.‬‬

‫‪ c‬به ما امکان رفتن به مرحله بالتر و تعريف متغیر را مي دهد‪ ،‬که اشاره گر نامیده مي شود‪ .‬شامل آدرس ( يعني "‪( ) “ points to‬‬

‫اشاره به ) متغیر های ديگراست‪ .‬برای مثال‬

‫‪ px‬را به عنوان اشاره گر به اشیاء نوع شناور تعريف مي کند‪ ،‬و آن را برابر با آدرس ‪ x‬قرار مي دهد‬

‫;‪float x‬‬ ‫;‪float* px‬‬ ‫;‪x = 6.5‬‬ ‫;‪px = &x‬‬

‫اشاره گررا برای متغیر استفاده مي کند‪.‬‬

‫محتوای مکان حافظه رجوع شده توسط اشاره گر با استفاده از عملوند "*” بدست مي آيد‪ ( .‬اين اشاره گر ‪،‬اشاره گر مرجع نامیده مي‬

‫شود )‬

‫بنابراين‪ *px ،‬به مقدار ‪ x‬مراجعه مي کند‪.‬‬

‫‪ c‬به ما اجازه اجرای عملگرهای حسابي را با استفاده از اشاره گرها مي دهد‪ .‬البته آگاه باشید که واحد(‪ )UNIT‬در اشاره گر حسابي‬

‫اندازه ( بر حسب بايت ) شي که اشاره گر‪ ،‬به آن اشاره مي کند است‪ .‬برای مثال‪ ،‬اگر ‪ px‬يك اشاره گر به متغیر ‪ x‬از نوع حقیقي باشد‪،‬‬

‫عبارت ‪ px + 1‬به بیت يا بايت بعدی حافظه مراجعه نمي کند بلکه به مکان نوع حقیقي بعد از ‪( x‬چهار بايت بعد در بیشترايستگاههای‬ ‫کاری) مراجعه مي کند‪.‬‬

‫اگر ‪ x‬از نوع مضاعف باشد ‪ px +1‬به مکان ‪ ۸‬بايت ( اندازه مضاعف ) بعد مراجعه مي کند‪ .‬و مانند آن‪ .‬فقط اگر ‪ x‬از نوع کاراکتر باشد‬

‫‪ px +1‬واقعا به بايت بعدی در حافظه مراجعه مي کند‪.‬‬

‫بنابراين‪ ،‬در‬

‫;‪char* pc‬‬ ‫;‪float* px‬‬ ‫;‪float x‬‬ ‫;‪x = 6.5‬‬ ‫;‪px = &x‬‬


‫محیط برنامه سازی لینوکس‬

‫‪169/322‬‬

‫;‪pc = )char*( px‬‬ ‫(( ‪ )*chart‬در خط آخر يك " طرح“ است که يك نوع داده را به نوع ديگر تبديل مي کند ) ‪ px :‬و ‪ pc‬هر دو به يك مکان در حافظه‬ ‫اشاره مي کنند‪.‬يعني آدرس ‪ .x‬البته ‪ px+1‬و ‪ pc+1‬به مکانهای متفاوتي از حافظه اشاره مي کنند‪.‬‬

‫به کد ساده زير توجه کنید‪:‬‬

‫‪/* x and y are of float type‬‬ ‫‪*/‬‬ ‫‪/* fp and fp2 are pointers to float */‬‬ ‫‪*/‬‬

‫‪/* x now contains the value 6.5‬‬

‫()‪void main‬‬ ‫}‬ ‫;‪float x, y‬‬ ‫;‪float *fp, *fp2‬‬ ‫;‪x = 6.5‬‬

‫‪/* print contents and address of x */‬‬ ‫;(‪printf)"Value of x is %f, address of x %ld\n", x, &x‬‬ ‫‪/* fp now points to location of x */‬‬ ‫‪*/‬‬

‫;‪fp = &x‬‬

‫‪/* print the contents of fp‬‬ ‫;(‪printf)"Value in memory location fp is %f\n", *fp‬‬

‫‪/* change content of memory location */‬‬ ‫;‪*fp = 9.2‬‬ ‫;(‪printf)"New value of x is %f = %f \n", *fp, x‬‬ ‫‪/* perform arithmetic‬‬

‫‪*/‬‬

‫;‪*fp = *fp + 1.5‬‬ ‫;(‪printf)"Final value of x is %f = %f \n", *fp, x‬‬ ‫‪*/‬‬

‫‪/* transfer values‬‬

‫;‪y = *fp‬‬ ‫;‪fp2 = fp‬‬ ‫;(‪printf)"Transfered value into y = %f and fp2 = %f \n", y, *fp2‬‬

‫{‬

‫اين کد را اجرا کنید و نتايج اين عملوند های مختلف را ببینید‪ .‬دقت کنیدکه‪ ،‬زمانیکه مقدار اشاره گر ( اگر شما آن را با ‪ printf‬چاپ‬ ‫کنید ) نوعا يك متغیر بزرگ است؛ مکان خاصي از حافظه در کامپیوتر‪ ،‬را مشخص مي کند‪ .‬اشاره گرها مقادير صحیح نیستند – آنها‬

‫يك نوع داده کامل متفاوت هستند‪.‬‬

‫‪­۷‬آرايه ها‪:‬‬ ‫آرايه ها از هر نوع مي توانند در ‪ c‬شکل بگیرند‪ .‬نحو آن ساده است‪:‬‬

‫[بعد] نام آرايه‬


‫محیط برنامه سازی لینوکس‬

‫‪170/322‬‬

‫در ‪ ،c‬آرايه ها از ‪ 0‬شروع مي شوند‪ .‬عناصر آرايه مکانهای مجاور در حافظه را اشغال مي کنند‪.‬‬

‫‪ c‬با نام آرايه مانند اينکه آنها يك اشاره گر به اولین عنصر باشد رفتار مي کنند‪ .‬اين در فهمیدن اينکه چگونه محاسبات توسط آرايه ها‬ ‫انجام گیرد مهم است‪ .‬بنابراين‪ ،‬اگر ‪ v‬يك آرايه باشد ‪ *V‬يك چیزی است نظیر [‪ *)v+1( , v]0‬چیزی نظیر [ ‪ v]1‬و به همین‬

‫ترتیب‪.‬‬

‫اشاره گر برای يك ارايه استفاده مي شود‪.‬‬ ‫به کد زير توجه کنید‪ ،‬که کاربرد اشاره گرها را با مثال توضیح مي دهد ‪.‬‬

‫‪#define SIZE 3‬‬ ‫()‪void main‬‬ ‫}‬ ‫;[‪float x]SIZE‬‬ ‫;‪float *fp‬‬ ‫;‪int i‬‬

‫‪/* initialize the array x‬‬ ‫‪*/‬‬ ‫‪/* use a "cast" to force i‬‬ ‫‪*/‬‬ ‫‪/* into the equivalent float‬‬ ‫‪*/‬‬ ‫(‪for )i = 0; i < SIZE; i++‬‬ ‫;‪x]i[ = 0.5*)float(i‬‬ ‫‪/* print x‬‬ ‫‪*/‬‬ ‫(‪for )i = 0; i < SIZE; i++‬‬ ‫;([‪printf)" %d %f \n", i, x]i‬‬ ‫‪/* make fp point to array x‬‬ ‫‪*/‬‬ ‫;‪fp = x‬‬ ‫‪/* print via pointer arithmetic */‬‬ ‫‪/* members of x are adjacent to */‬‬ ‫‪/* each other in memory‬‬ ‫‪*/‬‬ ‫‪/* *)fp+i( refers to content of */‬‬ ‫‪/* memory location )fp+i( or x]i[ */‬‬ ‫(‪for )i = 0; i < SIZE; i++‬‬ ‫;((‪printf)" %d %f \n", i, *)fp+i‬‬

‫{‬

‫( عبارت "‪ ”i++‬مختصر نويسي ‪ c‬برای " ‪ ”i= i+1‬است )‪ x]i [ .‬يعني ‪ i‬اولین عنصر آرايه ‪ fp=x, x‬به شروع ‪ x‬اشاره مي کند‪ ،‬سپس‬ ‫( ‪ *)fp+i‬محتوای آدرس ‪ i‬مکانهای بعد از ‪ fp‬است‪ .‬که [ ‪ x]i‬مي باشد‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪171/322‬‬

‫‪ ­۸‬آرايه هاي كاراكتري‬ ‫يك ثابت رشته ای‪ ،‬نظیر "‪”I am a string‬‬

‫يك آرايه از کاراکتر ها مي باشد‪ .‬که به طور داخلي در ‪ c‬توسط کاراکترهای اسکي (‪ )ASCII‬در رشته موجود است‪.‬‬

‫يعني "‪ ، ”i‬فاصله و "‪ ”a‬و "‪ ”m‬و ‪ ........‬برای رشته بال‪ ،‬وبا کاراکتر ويژه ‪ /0‬پايان يافته بنابراين برنامه مي توانند انتهای رشته را پیدا‬ ‫کنند‪.‬‬

‫ثابت های رشته ای اغلب در ايجاد خروجي کد قابل فهم با استفاده از ‪ printf‬بکار مي روند‪.‬‬

‫;("‪printf)"Hello, world\n‬‬ ‫;(‪printf)"The value of a is: %f\n", a‬‬ ‫ثابت های رشته مي توانند با متغیرها در ارتباط باشند‪ c .‬متغیر نوع ‪ char‬را فراهم کرده‪ .‬که مي تواند شامل يك کاراکتر باشد – ‪ ۱‬بايت‬

‫– در يك زمان‪ .‬يك رشته کاراکتر در يك حافظه نوع کاراکتری ذخیره مي شود‪ ،‬يك کاراکتر اسکي در مکان ‪.‬هرگز فراموش نکنید که از‬ ‫آنجا که رشته ها بطور قرار دادی با کاراکتر پوچ“‪ ”\o‬خاتمه مي يابند‪ ،‬ما نیاز به يك مکان ذخیره اضافه در آرايه داريم!‬

‫کدهای ‪ c‬هیچ عملوندی را برای دستکاری يکباره رشته های درست فراهم نکرده‪ .‬رشته ها يا توسط اشاره گرها يا از طريق روال های‬ ‫خاص قابل دسترسي از کتابخانه استاندارد رشته ‪ string‬دستکاری مي شوند‪ .‬استفاده از اشاره گر کاراکتری نسبتا ساده است چون نام‬ ‫آرايه فقط اشاره گر به اولین عنصر آن مي باشد‪.‬‬

‫به کد زير توجه کنید‪:‬‬

‫()‪void main‬‬ ‫}‬ ‫;[‪char text_1]100[, text_2]100[, text_3]100‬‬ ‫;‪char *ta, *tb‬‬ ‫;‪int i‬‬ ‫‪/* set message to be an arrray */‬‬ ‫‪/* of characters; initialize it */‬‬ ‫‪/* to the constant string "..." */‬‬ ‫‪/* let the compiler decide on */‬‬ ‫[] ‪/* its size by using‬‬ ‫‪*/‬‬ ‫;"?‪char message][ = "Hello, I am a string; what are you‬‬ ‫;(‪printf)"Original message: %s\n", message‬‬ ‫‪/* copy the message to text_1 */‬‬ ‫‪/* the hard way‬‬ ‫‪*/‬‬

‫;‪i=0‬‬ ‫( '‪while ) )text_1]i[ = message]i[( != '\0‬‬ ‫;‪i++‬‬ ‫;(‪printf)"Text_1: %s\n", text_1‬‬

‫‪/* use explicit pointer arithmetic */‬‬

‫;‪ta=message‬‬ ‫;‪tb=text_2‬‬


‫محیط برنامه سازی لینوکس‬

172/322

while ) ) *tb++ = *ta++ ( != '\0' ( ; printf)"Text_2: %s\n", text_2(; } k & ‫ توصیف اين کتابخانه در پیوست کتاب‬.‫کتابخانه استاندارد رشته شامل توابع مفید زيادی است ك رشته ها را دستکاری مي کنند‬

:‫ بعضي از توابع مفیدتر عبارتند از‬.‫ يافت مي شود‬R

.‫ را برمي گرداند‬s. ‫\” ؛‬0" ‫ شامل‬.‫ کپي مي کند‬s ‫ را به داخل‬ct

: char* strcpy )c,cf(

.‫ را بر مي گرداند‬s ،‫ کپي مي کند‬s ‫ را به داخل‬ct ‫ کاراکتر‬n : char * strncpy)c, cf, n( .‫ را بر مي گرداند‬s ‫ الحاق مي کند؛‬s ‫ را به انتهای‬ct : char * strncat )c, ct(

.‫ را بر مي گرداند‬s; ‫\” خاتمه يافته‬n" ‫ با‬،‫ االحاق مي کند‬s ‫ را به انتهای‬ct ‫ کاراکتر‬n :char* strncat )c, ct, n(

‫ مقدار مثبت را برمي‬cs>ct ‫ مقدار منفي و اگر‬cs<ct ‫ اگر‬، 0 ‫ باشد‬cs=ct ‫ را مقايسه مي کند؛ اگر‬ct ‫ و‬cs : int strcmp )cs,ct(

‫گرداند‬

.‫ را بر مي گرداند‬NULL ‫ را بر مي گرداند يا مقدار‬cs ‫ در‬c ‫ اشاره گر به اولین رخداد‬:char* strchr )cs, c( .‫ را بر مي گرداند‬cs ‫ طول‬:size – t strlen )cs(

).‫ يك نوع صحیح است‬n ‫ تبديل شده به صحیح و‬char ‫ يك کاراکتر از نوع‬c ، char* ‫ ثابت‬ct ‫ و‬cs .‫ هستند‬char * ‫ از نوع‬t ‫ و‬s (

#include < string.h>

.‫ توجه کنید‬.‫به کد زير که از بعضي از اين توابع استفاده مي کند‬

void main)( } char line]100[, *sub_text; /* initialize string */ strcpy)line,"hello, I am a string;"(; printf)"Line: %s\n", line(; /* add to end of string */ strcat)line," what are you?"(; printf)"Line: %s\n", line(; /* find length of string */ /* strlen brings back */ /* length as type size_t */ printf)"Length of line: %d\n", )int(strlen)line((; /* find occurence of substrings */ if ) )sub_text = strchr ) line, 'W' ( (!= NULL ( printf)"String starting with \"W\" ->%s\n", sub_text(; if ) ) sub_text = strchr ) line, 'w' ( (!= NULL ( printf)"String starting with \"w\" ->%s\n", sub_text(;


‫محیط برنامه سازی لینوکس‬

‫‪173/322‬‬

‫( ‪if ) ) sub_text = strchr ) sub_text, 'u' ( (!= NULL‬‬ ‫;(‪printf)"String starting with \"w\" ->%s\n", sub_text‬‬

‫}‬ ‫قابليت هاي (‪ ‬ورودي ‪ /‬خروجي)‪I/o  ‬‬ ‫سطح کاراکتر ‪I/o‬‬ ‫‪ ( c‬از طريق کتابخانه هايش ) روتین های گوناگون ‪ 1/0‬را فراهم کرده است‪ .‬در سطح کاراکتر ( )‪ getchar‬کاراکتر را در يك زمان‬ ‫از ‪ stdin‬مي خواند‪ .‬هنگامیکه ( )‪ putchar‬يك کاراکتر را در يك زمان روی ‪ stdout‬مي نويسد‪ .‬برای مثال‪ ،‬توجه کنید‪:‬‬

‫‪include < stdio.h>#‬‬ ‫()‪void main‬‬ ‫}‬ ‫;‪int i, nc‬‬ ‫;‪nc = 0‬‬ ‫;()‪i = getchar‬‬ ‫} (‪while )i != EOF‬‬ ‫;‪nc = nc + 1‬‬ ‫;()‪i = getchar‬‬ ‫{‬ ‫;(‪printf)"Number of characters in file = %d\n", nc‬‬

‫{‬

‫اين برنامه تعداد کاراکترها را در جريان ورودی مي شمارد‪ ( .‬مثل در يك فايل لوله شده در زمان اجرا)‬

‫کد کاراکترها را (هر چقدرممکن است باشند) از ‪( stdin‬صفحه کلید) خوانده‪ stdout ،‬را (پايانه ‪ x‬که شما از آن اجرا مي کنید) برای‬

‫خروجي استفاده نموده و پیام خطايي برای ‪ ( stderr‬معمول پايانه ‪ x‬شما) مي نويسد‪ .‬اين جريانات همیشه در زمان اجرا تعريف مي‬

‫شوند‪( EOF .‬پايان فايل) مقدار مشخصي را بر مي گرداند‪ .‬که درـ ‪ stdioh‬تعريف شده وتوسطـ (‬

‫)‪ getchar‬هنگامیکه در زمان‬

‫خواندن با نشانه ‪ end- of-file‬مواجه شد‪ ،‬بر گردانده مي شود‪ .‬مقدار آن به کامپیوتر بستگي دارد‪ .‬البته کامپايلر ‪ c‬اين واقعیت را از کاربر‬ ‫با تعريف متغیر ‪ EOF‬پنهان مي کند‪ .‬بنابراين برنامه کاراکتر ها را از ‪ stdin‬خوانده و مجموع آن را در شمارنده ‪ nc‬نگه مي دارد‪ .‬تا‬

‫زمانیکه با "‪( ”end of file‬انتهای فايل) روبرو شود‪.‬‬

‫يك برنامه نويس با تجربه ‪ c‬احتمال اين برنامه را به صورت زير کد مي کند ‪:‬‬

‫‪<include < stdio.h#‬‬ ‫()‪void main‬‬ ‫}‬ ‫;‪int c, nc = 0‬‬


‫محیط برنامه سازی لینوکس‬

‫‪174/322‬‬

‫;‪while ) )c = getchar)(( != EOF ( nc++‬‬ ‫;(‪printf)"Number of characters in file = %d\n", nc‬‬ ‫‪ c‬امکان عبارات مختصر زيادی را مي دهد‪ .‬معمول با قابلیت خوانائي!‬

‫{‬

‫( ) در دستورات ( ( )‪ )c=getchar‬اجرای فراخواني ( ) ‪ getchar‬را بیان مي کند‪ .‬و نتیجه را ‪ c‬قبل از مقايسه آن با ‪ EOF‬انتساب‬ ‫مي کند‪( .‬قرار مي دهد)‬

‫کروشه ها اينجا لزم است‪ .‬بیاد داشته باشید نماد گذاری ‪ ( nc++‬و در حقیقت‪ ) ++nc ،‬راه ديگری برای نوشتن ‪ nc=nc+1‬است‪.‬‬

‫(تفاوت بین نمادگذاری پیشوند و پسوند است که در ‪ nc ، ++nc‬قبل از اينکه استفاده شود افزايش يافته‪.‬در حالیکه در ‪ nc ، nc++‬قبل‬ ‫از اينکه افزايش يابد استفاده مي شود‪.‬‬

‫در اين مثال خاص ‪،‬هر دو انجام شده ) اين نماد گذاری فشرده تر است و اغلب بطور مؤثرتری توسط مترجم کد مي شود‪.‬‬

‫فرمان ‪ wc‬يونیکس کاراکترها و کلمات و خطوط را در يك فايل مي شمارد‪ .‬برنامه بال مي تواند بعنوان ‪ wc‬شما مورد توجه قرار گیرد‪.‬‬

‫اجازه دهید شمارنده ای را برای خطوط اضافه کنم‪.‬‬

‫>‪< #include < stdio.h‬‬ ‫()‪void main‬‬ ‫}‬ ‫;‪int c, nc = 0, nl = 0‬‬ ‫( ‪while ) )c = getchar)(( != EOF‬‬ ‫}‬ ‫;‪nc++‬‬ ‫;‪if )c == '\n'( nl++‬‬ ‫{‬ ‫‪printf)"Number of characters = %d, number of lines = %d\n",‬‬ ‫;(‪nc, nl‬‬ ‫شما مي توانید در مورد راههای شمارش تعداد کلمات در فايل فکر کنید؟‬

‫{‬

‫قابلیت های سطح بالی ‪I/O‬‬

‫هنوز مي بینیم که ‪ printf‬خروجي فرمت بندی شده با ‪ stdout‬را بکار مي بردودر مقابل دستور خواندن از ‪ scanf ، stdin‬است‪ .‬نحو‬

‫آن‬

‫; ( ‪scanf )“format string “ ,variables‬‬ ‫مانند ‪ printf‬است‪ .‬فرمت رشته ممکن است شامل فاصله ها يا تب ها باشد‪ ( .‬چشم پوشي مي شود) کاراکترهای اسکي معمولي‪ ،‬که‬

‫بايد آنها را با ‪ stdin‬مطابقت داد‪ ،‬و تبديل مشخصات مانند ‪ printf‬دستورات معادل برای خواندن يا نوشتن رشته های کاراکتری موجود‬

‫است‪ .‬آنها عبارتند از‪:‬‬

‫;(‪sprintf)string, "format string", variables‬‬ ‫;(‪scanf)string, "format string", variables‬‬


‫محیط برنامه سازی لینوکس‬

‫‪175/322‬‬

‫اين کد را ترجمه و اجرا کنید؛ سپس ويرايشگری را برای خواندن فايل ‪ foo.dat‬بکار ببريد‪.‬‬

‫توابع‬ ‫توابع برای استفاده آسانند؛ آنها اجازه می دهند كه برنامه های پيچيده به بلوک های كوچک تری تجزیه شوند‪ ،‬هر كدام از آنها‬ ‫برای نوشتن‪ ،‬خواندن و نگهداری آسانترند‪ .‬ما تا كنون با تابع ‪ main‬بر خورد داشته و روال های ریاضی از كتابخانه های استاندارد‬ ‫استفاده كرده ایم‪ .‬اكنون اجازه دهيد به برخی دیگر از توابع كتابخانه ای و چگونگی نوشتن و استفاده از آنها نگاهی بيندازیم ‪.‬‬

‫فراخواني يك تابع‬ ‫فراخواني يك تابع در ‪ C‬بسادگي شامل مراجعه به نام آن توسط نشانوندهای مناسب مي باشد‪ .‬مترجم مطابقت بین آرگومانها در دنباله‬ ‫فراخواني و تعريف تابع را بررسي مي کند‪.‬‬

‫توابع کتابخانه ای عموما در فرم منبع در دسترس ما نیستند‪ .‬بررسي نوع نشانوند از طريق استفاده از فايلهای سرآيند ( مانند ‪) stdion.h‬‬

‫انجام مي شود که شامل همه اطلعات لزم مي باشد ‪ .‬برای مثال‪ ،‬همانطور که بزودی خواهیم ديد‪ ،‬بمنظور استفاده از کتابخانه رياضي‬ ‫استاندارد شما بايد ‪ math.h‬را از طريق دستور‬

‫> ‪# include <math.h‬‬

‫در بالی فايل محتوی کدتان اضافه کنید‪ .‬فايلهای سرآيند رايجتر عبارتند از‪:‬‬

‫>‪ : <stdio.h‬تعريف روالهای ‪I/O‬‬

‫>‪ : <ctype.h‬بعريف روالهای دستکاری کارکترها‬ ‫>‪ : <string.h‬تعريف روالهای دستکاری رشته‬ ‫>‪ : <math.h‬تعريف روالهای رياضي‬

‫>‪ : <stdlib.h‬تعريف تبديل عدد تخصیص حافظه و وظايف ( کارهای ) مشابه‬ ‫>‪ :<time.h‬تعريف روالهای زمان دستکاری‬

‫به علوه‪ ،‬فايلهای سرآيند زير هم موجود است‪:‬‬

‫>‪ :<assert.h‬تعريف روالهای تشخیص‬

‫>‪ :<setjmp.h‬تعری فرآخواني های تابع غیر محلي‬ ‫>‪ : <signal.h‬بعريف گرداننده های سیگنال‬

‫>‪ :<limits.h‬تعريف ثابت هايي از نوع صحیح‬ ‫>‪ : <float.h‬تعريف ثابتهايي از نوع شناور‬

‫پیوست ‪ B‬در کتاب ‪ K & R‬اين کتابخانه ها را با جزئیات بیشتر توضیح مي دهد‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪176/322‬‬

‫نوشتن تابع های خودتان‬

‫يك تابع دارای طرح بندی زير مي باشد‪:‬‬

‫(فهرست نشانوند اگر لزم باشد) نام تابع‬

‫نوع بازگشتي )‬

‫{‬ ‫‪ ..........‬اعلن محلي ‪.........‬‬ ‫‪ ...........‬دستورات ‪...........‬‬ ‫; مقدار بازگشتي ‪return‬‬ ‫{‬

‫اگر نوع بازگشتي حذف شده باشد‪ C ،‬بطور پیش فرض از ‪ int‬استفاده مي کند‪ .‬مقدار بازگشتي بايد از نوع اعلن شده باشد‪.‬‬

‫يك تابع ممکن است بطور ساده يك وظیفه را بدون بازگشت هیچ مقداری اجرا کند‪ .‬در اين حالت دارای طرح بندی زير مي باشد‪:‬‬

‫(فهرست نشانوند اگر لزم باشد ) نام تابع‬

‫‪void‬‬

‫}‬ ‫‪ ...........‬اعلن های محلي ‪........‬‬ ‫‪ .........‬دستورات ‪..........‬‬ ‫{‬

‫يك مثال از فراخواني تابع ‪ x‬به کد زير توجه کنید‪:‬‬

‫‪/* include headers of library  */               ‬‬ ‫‪/* defined for all routines */‬‬ ‫‪/* in the file‬‬ ‫‪*/‬‬ ‫>‪#include < stdio.h‬‬ ‫>‪#include < string.h‬‬ ‫‪/* prototyping of functions */‬‬ ‫‪/* to allow type checks by */‬‬ ‫‪/* the compiler‬‬ ‫‪*/‬‬ ‫()‪void main‬‬ ‫}‬ ‫;‪int n‬‬ ‫;[‪char string]50‬‬ ‫‪/* strcpy)a,b( copies string b into a */‬‬ ‫‪/* defined via the stdio.h header */‬‬ ‫;("‪strcpy)string, "Hello World‬‬ ‫‪/* call own function */‬‬ ‫;(‪n = n_char)string‬‬ ‫;(‪printf)"Length of string = %d\n", n‬‬ ‫‪/* definition of local function n_char */‬‬

‫{‬


‫محیط برنامه سازی لینوکس‬

‫‪177/322‬‬

‫([]‪int n_char)char string‬‬ ‫}‬ ‫‪/* local variable in this function */‬‬ ‫;‪int n‬‬ ‫‪/* strlen)a( returns the length of */‬‬ ‫‪/* string a‬‬ ‫‪*/‬‬ ‫‪/* defined via the string.h header */‬‬ ‫;(‪n = strlen)string‬‬ ‫(‪if )n > 50‬‬ ‫;("‪printf)"String is longer than 50 characters\n‬‬ ‫‪/* return the value of integer n */‬‬

‫;‪return n‬‬

‫{‬

‫نشانوند ها همیشه توسط مقدار درفراخواني های تابع رد مي شوند‪ .‬يعني کپي های محلي مقادير نشانوند ها از روالها عبور مي کنند‪ .‬هر‬

‫تغییر در نشانوند ها بطور دروني در تابع فقط در کپي های محلي نشانوند ها ايجاد مي شود‪.‬‬

‫بمنظور تغییر ( يا تعريف ) نشانوند درفهرست نشانوند‪ ،‬اين نشانوند بايد بعنوان يك آدرس عبور کند‪ ( ،‬در نتیجه الزام ‪ C‬برای تغییر‬

‫نشانوند واقعي در روال فراخواني‪).‬‬

‫بعنوان يك مثال به تعويض دو عدد بین متغیرها توجه کنید‪ ،‬ابتدا اجازه دهید آنچه اتفاق مي افتد را اگر متغیرها توسط مقدار عبور کنند‬ ‫را با مثال نشان دهیم‬

‫>‪#include < stdio.h‬‬ ‫;(‪void exchange)int a, int b‬‬ ‫‪/* WRONG CODE */‬‬

‫()‪void main‬‬ ‫}‬ ‫;‪int a, b‬‬

‫;‪a = 5‬‬ ‫;‪b = 7‬‬ ‫;(‪printf)"From main: a = %d, b = %d\n", a, b‬‬ ‫;(‪exchange)a, b‬‬ ‫;(" ‪printf)"Back in main:‬‬ ‫;(‪printf)"a = %d, b = %d\n", a, b‬‬

‫{‬

‫(‪void exchange)int a, int b‬‬ ‫}‬ ‫;‪int temp‬‬ ‫;‪temp = a‬‬ ‫;‪a = b‬‬ ‫;‪b = temp‬‬


‫محیط برنامه سازی لینوکس‬

‫‪178/322‬‬

‫;(" ‪printf)" From function exchange:‬‬ ‫;(‪printf)"a = %d, b = %d\n", a, b‬‬ ‫اين کد را اجرا کنید و ملحظه کنید که ‪ a‬و ‪ b‬عوض نشده اند‪ :‬فقط کپي های نشانوند ها تعويض شده اند‪:‬‬ ‫البته روش صحیح انجام اين کار استفاده از اشاره گرهاست‪:‬‬

‫{‬

‫>‪#include < stdio.h‬‬ ‫;( ‪void exchange ) int *a, int *b‬‬ ‫‪/* RIGHT CODE */‬‬

‫()‪void main‬‬ ‫}‬ ‫;‪int a, b‬‬

‫;‪a = 5‬‬ ‫;‪b = 7‬‬ ‫;(‪printf)"From main: a = %d, b = %d\n", a, b‬‬ ‫;(‪exchange)&a, &b‬‬ ‫;(" ‪printf)"Back in main:‬‬ ‫;(‪printf)"a = %d, b = %d\n", a, b‬‬

‫{‬

‫( ‪void exchange ) int *a, int *b‬‬ ‫}‬ ‫;‪int temp‬‬ ‫;‪temp = *a‬‬ ‫;‪*a = *b‬‬ ‫;‪*b = temp‬‬ ‫;(" ‪printf)" From function exchange:‬‬ ‫;(‪printf)"a = %d, b = %d\n", *a, *b‬‬

‫{‬

‫قواعد ملموس اينجا عبارتند از ‪:‬‬

‫•شما متغیرهای منظم ( باقاعده ) را استفاده مي کنید اگر تابع مقادير آن نشانوند ها را متغیر ندهد‪.‬‬ ‫•شما بايد از اشاره گرها استفاده کنید اگر تابع مقادير آن نشانوندها را تغییر دهد‪.‬‬

‫نشانوندهاي خط فرمان‬ ‫اين يك تمرين استاندارد يونیکس برای اطلعات در مورد گذر از خط فرمان به برنامه به طور مستقیم از طريق استفاده از يك يابیشتر از‬ ‫نشانوندهای خط فرمان است‪ )switches( .‬سوئیچ ها نوعا برای تغییر رفتار برنامه‪ ،‬ياتنظیم مقادير برخي پارامترهای ورودی استفاده مي‬


‫محیط برنامه سازی لینوکس‬

‫‪179/322‬‬

‫شود‪ .‬شما تا کنون با چند مورد از اينها روبرو شده ايد‪ .‬برای مثال‪ ،‬فرمان «‪ »ls‬فايلها را در فهرست جاری شما لیست مي کند‪.‬‬

‫ولي هنگامیکه سوئیچ ‪ -۱‬اضافه شود‪ »ls -1 « ،‬يك فهرست طولني رادر عوض تولید مي کند‪ .‬به طور مشابه « ‪ »ls -1 -a‬يك فهرست‬

‫طولني‪ ،‬شامل فايلهای پنهان راتولید مي کند‪ .‬فرمان «‪ »tail -20‬و ‪ ۲۰‬خط آخر فايل را ( به جای مقدار پیش فرض ‪ ) ۱۰‬چاپ مي‬ ‫کند‪ ،‬و مانند آن ‪.‬‬

‫به طور فرضي‪ ،‬سوئیج ها بسیار شبیه نشانوندهای توابع در ‪ C‬رفتار مي کنند‪ .‬و آنها از برنامه ‪ C‬از سیستم عامل عبور مي کنند‪ .‬دقیقا با‬ ‫همان روشي که نشاوندها بین توابع عبور مي کنند‪ .‬تا کنون‪ ،‬دستورات (‬

‫) ‪ main‬در برنامه های ما هیچ چیزی بین پرانتز ها نداشته‪.‬‬

‫بنابراين‪ ،‬يونیکس واقعا برای برنامه ها (هنگامیکه برنامه نويس انتخاب مي کند که از اطلعات استفاده کنديا نه ) دو نشانوند برای ‪main‬‬

‫رافراهم مي سازد‪.‬‬

‫يك آرايه از رشته های کاراکتری‪ ،‬که بطور مرسوم ‪ argv‬نامیده مي شود و يك صحیح‪ ،‬که معمول ‪ argv‬نام دارد‪ .‬که تعداد رشته های‬ ‫آرايه رامشخص مي کند‪ .‬دستور کامل خط اول برنامه عبارتست از‪:‬‬

‫(‪main ) integer ,char** argv‬‬ ‫( نحو ‪ char**argv‬مشخص مي کند ‪ argv‬بايد اشاره گری به اشاره گر کاراکتر باشد‪ ،‬که آن‪ ،‬اشاره گری است به آرايه کاراکتر ( يك‬

‫رشته کارکتری ) از لحاظ کلمات‪ ،‬يك آرايه از رشته های کاراکتری‪ .‬شما همچنین مي توانید آن را به صورت ( ) ‪ chat*argv‬بنويسید‬

‫به هرحال خیلي در مورد جزئیات نحو آن نگران نباشید‪ .‬کاربرد آرايه در زير واضح تر خواهد شد‪) .‬‬

‫هنگامیکه شما يك برنامه را اجرا مي کنید‪ ،‬آرايه ‪ argv‬شامل همه اطلعات خط فرمان‪ ،‬هنگامیکه شما فرماني را وارد کرديد مي شود‪۰ .‬‬

‫رشته ها با فضای سفید مشخص مي شوند) شامل خود فرمان صحیح ‪ argv‬تعداد کل رشته ها را مي دهد‪ ،‬بنابراين برابر است با تعداد‬ ‫نشانوندها به اضافه يك‪ .‬برای مثال اگر شما ‪2 -g -x 3 q‬‬

‫‪ a.out -i‬راتايپ کنید برنامه مقادير زير را دريافت مي کند‪.‬‬

‫‪argc = 7‬‬ ‫"‪argv]0[ = "a.out‬‬ ‫"‪argv]1[ = "-i‬‬ ‫"‪argv]2[ = "2‬‬ ‫"‪argv]3[ = "-g‬‬ ‫"‪argv]4[ = "-x‬‬ ‫"‪argv]5[ = "3‬‬ ‫"‪argv]6[ = "4‬‬ ‫دقت کنید که نشانوندها‪ ،‬حتي مقادير عددی‪ ،‬در اين مورد رشته هستند‪ .‬اين وظیفه برنامه نويس است که آنها را کد گشايي کرده و‬

‫تصمیم بگیرد با آنها چه بکند‪.‬‬

‫برنامه زير بطور ساده نام و نشانوندهايش را چاپ مي کند‪.‬‬

‫>‪#include < stdio.h‬‬ ‫(‪main)int argc, char** argv‬‬ ‫}‬ ‫;‪int i‬‬ ‫;(‪printf)"argc = %d\n", argc‬‬


‫محیط برنامه سازی لینوکس‬

‫‪180/322‬‬

‫(‪for )i = 0; i < argc; i++‬‬ ‫;([‪printf)"argv]%d[ = \"%s\"\n", i, argv]i‬‬

‫{‬

‫برنامه نويسان يونیکس قرار دادهای مشخصي در مورد چگونگي تفسیر فهرست نشانوندها دارند‪ .‬آنها اجباری نیستند بلکه برنامه شما را‬ ‫بای استفاده و فهم ديگران آسانتر مي سازند‪ .‬اول اينکه اصطلحات سوئیچ ها و کلیدها با کاراکتر « ‪ » -‬شروع مي شوند‪ .‬اين باعث‬

‫مي شود که به آساني آنها را تشخیص دهید‪ .‬سپس‪ ۷‬بسته به سوئیچ‪ ،‬نشانوندها ممکن است شامل اطلعاتي که بعنوان صحیح‪ ،‬شناور يا‬

‫فقط بعنوان يك رشته کاراکتری نگه داشته شده اند تفسیر شوند‪ .‬با اين قرار دادها‪ ،‬رايجترين راه تجزيه فهرست نشانوند بوسیله حلقه‬

‫‪ For‬و يك دستور ‪ switch‬مي باشد‪.‬‬ ‫مانند زير‪:‬‬

‫>‪#include < stdio.h‬‬ ‫>‪#include < stdlib.h‬‬ ‫(‪main)int argc, char** argv‬‬ ‫}‬ ‫‪/* Set defaults for all parameters: */‬‬ ‫;‪int a_value = 0‬‬ ‫;‪float b_value = 0.0‬‬ ‫;‪char* c_value = NULL‬‬ ‫;‪int d1_value = 0, d2_value = 0‬‬ ‫;‪int i‬‬ ‫‪/* Start at i = 1 to skip the command name. */‬‬ ‫} (‪for )i = 1; i < argc; i++‬‬ ‫‪/* Check for a switch )leading "-"(. */‬‬ ‫} ('‪if )argv]i[]0[ == '-‬‬ ‫‪/* Use the next character to decide what to do. */‬‬ ‫} ([‪switch )argv]i[]1‬‬ ‫;([‪a_value = atoi)argv]++i‬‬ ‫;‪break‬‬

‫‪case 'a':‬‬

‫;([‪b_value = atof)argv]++i‬‬ ‫;‪break‬‬

‫‪case 'b':‬‬

‫;[‪c_value = argv]++i‬‬ ‫;‪break‬‬

‫‪case 'c':‬‬


‫محیط برنامه سازی لینوکس‬

‫‪181/322‬‬

‫;([‪d1_value = atoi)argv]++i‬‬ ‫;([‪d2_value = atoi)argv]++i‬‬ ‫;‪break‬‬

‫‪case 'd':‬‬

‫{‬

‫{‬

‫{‬

‫;(‪printf)"a = %d\n", a_value‬‬ ‫;(‪printf)"b = %f\n", b_value‬‬ ‫;(‪if )c_value != NULL( printf)"c = \"%s\"\n", c_value‬‬ ‫;(‪printf)"d1 = %d, d2 = %d\n", d1_value, d2_value‬‬

‫{‬

‫دقت کنید که [ ‪ argv ]i[ ]j‬يعني ‪ j‬امین کاراکتر ‪ i‬امین کاراکتری دستور ‪ if‬راهنمای "‪ ( ”-‬کاراکتر ‪ ) 0‬را بررسي مي کند‪ .‬سپس دستور‬

‫‪ switch‬امکان تغییرهای گوناگون عملیاتي که بسته به کاراکتر بعدی در رشته گرفته مي شوند را مي دهد‪ ( .‬اينجا کاراکتر )‬

‫دقت کنید که استفاده از [ ‪ argv]++i‬برای افزايش ‪ i‬قبل از استفاده‪ ،‬اجازه مي دهد به رشته بعدی در يك دستور فشرده تکي دستیابي‬ ‫داشته باشیم‪ .‬توابع ‪ atoi‬و ‪ atof‬در ‪ stdlib.h‬تعريف شده اند‪.‬‬

‫آنها از رشته های کاراکتری به ترتیب به صحیح (‪ )ints‬و مضاعف (‪ )doubles‬تبديل مي کنند‪.‬‬

‫يك خط فرمان تايپ شده ممکن است چنین باشد‪:‬‬

‫‪a.out -a 3 -b 5.6 -c “I am a string” -d 222 111‬‬ ‫( کاربرد دبل کوتیشن ('') با ‪ -c‬در اينجا اطمینان مي دهد که پوسته با رشته کامل سرو کار داشته‪ ،‬شامل فاصله ها‪ ،‬بعنوان يك شي‬ ‫منفرد)‬

‫با قرارد دادی خطوط پیچیده فرمان مي توانند در اين روش بکار روند‪ .‬سر انجام‪ ،‬در اينجا يك برنامه ساده چگونگي جای دادن‬

‫دستورات تجزيه شده در تابع مجزا که هدف آن خط فرمان و تنظیم مقادير نشانوندهايش مي باشد را نشان مي دهد‪.‬‬

‫‪/********************************/‬‬ ‫*‪/‬‬ ‫‪*/‬‬ ‫‪/* Getting arguments from */‬‬ ‫*‪/‬‬ ‫‪*/‬‬ ‫‪/* the Command Line‬‬ ‫‪*/‬‬ ‫*‪/‬‬ ‫‪*/‬‬ ‫‪/********************************/‬‬ ‫‪/* Steve McMillan‬‬ ‫‪*/‬‬ ‫‪/* Written: Winter 1995 */‬‬ ‫>‪#include < stdio.h‬‬ ‫>‪#include < stdlib.h‬‬

‫(‪void get_args)int argc, char** argv, int* a_value, float* b_value‬‬


‫محیط برنامه سازی لینوکس‬

182/322

}

int i; /* Start at i = 1 to skip the command name. */ for )i = 1; i < argc; i++( } /* Check for a switch )leading "-"(. */ if )argv]i[]0[ == '-'( } /* Use the next character to decide what to do. */ switch )argv]i[]1[( }

{

{

{

case 'a':

*a_value = atoi)argv]++i[(; break;

case 'b':

*b_value = atof)argv]++i[(; break;

default:

fprintf)stderr, "Unknown switch %s\n", argv]i[(;

{

main)int argc, char** argv( } /* Set defaults for all parameters: */ int a = 0; float b = 0.0; get_args)argc, argv, &a, &b(;

{

printf)"a = %d\n", a(; printf)"b = %f\n", b(;

‫جعبه هاي محاوره‬ : ‫­ واسط هاي گرافيكي‬۱۲ ‫ ولي هنوز مي خواهید برنامه شما قادر به تغییر مقادير متغیرهای مشخص‬،‫فرض کنید شما نمي خواهید با تفسیر خط فرمان مواجه شويد‬


‫محیط برنامه سازی لینوکس‬

‫‪183/322‬‬

‫در يك روش محاوره ای باشد‪ .‬شما مي توانید برنامه را در يك سری خطوط ـ ‪ printf/scanf‬برای امتحان کاربرد در مورد اولويت‬ ‫هايشان ساده کنید‪.‬‬

‫‪.‬‬ ‫‪.        ‬‬

‫‪.‬‬ ‫;(" ‪printf)"Please enter the value of n:‬‬ ‫;(‪scanf)"%d", &n‬‬ ‫;(" ‪printf)"Please enter the value of x:‬‬ ‫;(‪scanf)"%f", &x‬‬ ‫‪.‬‬ ‫‪.‬‬ ‫‪.‬‬

‫ومانند آن‪ ،‬البته اين کار خوبي نخواهد بود اگر برنامه شما به عنوان بخشي از خط لوله (‪ )pipeline‬يا پايپ لين استفاده مي شود‪ .‬برای‬

‫مثال استفاده از برنامه گرافیکي ‪ ، plot – data‬چون پرسشها و پاسخها در جريان داده ها مخلوط مي شوند‪.‬‬

‫رفتار درست استفاده از يك واسط گرافیگي ساده است که يك جعبه محاوره تولید کند‪ ،‬اختیار پارمترهای گوناگون کلید در برنامه را به‬

‫شما مي دهد‪ .‬بسته های گرافیکي ما تعدادی از ابزارهای آسان برای استفاده از ساختارها و جعبه های مشابه را فراهم مي کند‪.‬‬

‫ساده ترين راه برای ست کردن متغیر صحیح ‪ n‬و متغیر شناور ‪ ( x‬يعني برای اجرای يك اثر مانند خطوط کد بال ) استفاده از جعبه‬ ‫محاوره مانند زير مي باشد‪:‬‬

‫‪/* Simple program to illustrate use of a dialog box */‬‬ ‫()‪main‬‬ ‫}‬ ‫‪/* Define default values: */‬‬ ‫;‪int n = 0‬‬ ‫;‪float x = 0.0‬‬ ‫‪/* Define contents of dialog window */‬‬ ‫;(‪create_int_dialog_entry)"n", &n‬‬ ‫;(‪create_float_dialog_entry)"x", &x‬‬ ‫‪/* Create window with name "Setup" and top-left corner at )0,0( */‬‬ ‫;(‪set_up_dialog)"Setup", 0, 0‬‬ ‫‪/* Display the window and read the results */‬‬ ‫;()‪read_dialog_window‬‬


‫محیط برنامه سازی لینوکس‬

‫‪184/322‬‬

‫‪/* Print out the new values */‬‬ ‫;(‪printf)"n = %d, x = %f\n", n, x‬‬

‫{‬

‫اين برنامه را با استفاده از نام مستعار ‪ cgfx‬برای پیوند در همه کتابخانه های لزم ترجمه کنید ‪.‬‬

‫دو خط ‪ create‬مدخلهای جعبه و متغیرهای وابسته به آنها را تعريف مي کند‪ set- up – dialog .‬جعبه ها را نام گذاری کرده و مکان‬ ‫آنها را تعريف مي کند‪ .‬سر انجام‪ read- dialog-window ،‬پنجره را بال پرانده ( باز مي کند) و به شما اجازه تغییر مقادير متغیرها را‬

‫مي دهد‪.‬‬

‫هنگامیکه برنامه اجرا مي شود‪ ،‬شما جعبه ای مشابه زير را خواهید ديد‪.‬‬

‫شكل‬ ‫اعداد نشان داده شده را تغییر داده‪ OK ،‬را فشار دهید‪ ( .‬يا فقط کلید ‪ Enter‬را بزنید‪).‬‬

‫تغییرات انجام مي شود‪ .‬همه آنها به همین صورت است‪ .‬بیشترين فايده اين مورد اينست که آن مستقل از روند داده ها از طريق‬ ‫‪ stdin/dstout‬عمل مي کند‪ .‬بطور کلي‪ ،‬شما مي توانید حتي عملیات هر مرحله را در پايپ لين بسیاری از فرمانهای زنجیره ای با‬

‫استفاده از يك جعبه محاوره برای هر کدام کنترل کنید ‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪185/322‬‬

‫فصل‪ ‬هفتم‪ : ‬ورودی‪ ‬خروجی‪ ‬استاندارد‬ ‫تاکنون ما از ابزار موجود برای ساخت ابزار جديد استفاده کرديم‪ ،‬اما محدود به اين هستیم که به طور معقول با شل ‪ sed ،‬و ‪ awk‬چه‬ ‫مي‌توان انجام داد‪ .‬در اين فصل ما قصد داريم‪ ،‬برخي از برنامه‌های ساده را به زبان برنامه‌نويسي ‪ C‬بنويسیم‪ .‬فلسفه اصلي ساختن چیزها‬

‫اين است که همکاری تا نفوذ بر بحث و بررسي و طرح برنامه‌ها ادامه يابد ـ ما مي‌خواهیم ابزاری را بوجود ‌آوريم که ديگران بتوانند‬ ‫استفاده کنند و به آنها اعتماد داشته باشند‪ .‬در هر مورد‪ ،‬ما سعي مي‌کنیم که يك استراتژی تحقق مناسب را نیز انجام دهیم ‪ :‬آغاز با‬ ‫حداقل میزان‪ ،‬که کار مفیدی را انجام دهد‪ ،‬سپس افزودن ويژگي‌ها و انتخابها (فقط) اگر مورد نیاز باشند‪.‬‬

‫دليل خوبي برای نوشتن برنامه‌های جديد از حافظه وجود دارند‪ .‬مي‌تواند به اين دلیل باشد که مشکل موجود نمي‌تواند فقط با‬

‫برنامه‌های موجود حل شود‪ .‬اين مورد اغلب زماني صحیح است که برنامه بايد به فايلهای غیر مبتني بپردازد‪ .‬برای مثال ـ اکثر‬

‫برنامه‌هايي که ما تاکنون نشان داده‌ايم‪ .‬حقیقتا ً فقط بر روی اطلعات متني به خوبي کار مي‌کنند‪ .‬و يا ممکن است دستیابي به توان يا‬

‫سودمندی مناسب با شل و ساير ابزارهای دارای هدف کلي‪ ،‬بسیار دشوار باشد‪ .‬در چنین مواردی ‪ ،‬يك نسخه شل مي‌تواند برای‬

‫اختصاص به تعريف و واسط کاربر از يك برنامه خوب باشد ‪0‬و اگر به خوبي کار کند ‪ ،‬نیازی به انجام مجدد آن نیست)‪ .‬برنامه ‪ zap‬از‬

‫فصل آخر‪ .‬مثال خوبي است ‪ :‬ابن برنامه فقط به چند دقیقه زمان برای نوشتن اولین نسخه در شل نیاز دارد و نسخه نهايي دارای يك‬ ‫واسط کاربر مناسب مي‌باشد ‪ ،‬اما بسیار کند مي‌باشد‪.‬‬

‫ما به زبان ‪ C‬خواهیم نوشت ‪ ،‬چون ‪ C‬يك زبان استاندارد از سیستم‌های يونیکس مي‌باشد ـ کرنل و همه برنامه‌های کاربر به زبان ‪C‬‬

‫نوشته مي‌شوند ـ و حقیقتاً از هیچ زبان ديگری‪ ،‬تقريباً به اين خوبي حمايت نمي‌شود‪ .‬ما فرض مي‌کنیم که شما زبان ‪ C‬را مي‌شناسید ‪،‬‬

‫حداقل تا اندازه‌ای که ‌آن را بخوانید‪ .‬اگر اين اينگونه نیست‪ ،‬زبان برنامه‌نويسي ‪ C‬را که نوشته ‪ . W.B‬کرنیگمان و ‪ M.D‬ريتچای‬ ‫مي‌باشد‪ .‬مطالعه کنید (پرنتیك ـ مال ‪.)1978‬‬

‫ما همچنین از کتابخانه استاندارد ‪ I / O‬استفاده خواهیم کرد‪ ،‬يك مجموعه از زيربرنامه‌هايي که خدمات موثر و قابل انتقال سیستم و ‪I /‬‬

‫‪ O‬را برای برنامه‌های ‪ C‬فراهم مي‌کند‪.‬‬

‫کتابخانه استاندارد ‪ I / O‬در همه سیستم‌های غیر يونیکس که از ‪ C‬حمايت مي‌کنند‪ ،‬در دسترس مي‌باشد‪ ،‬بنابراين‪ ،‬برنامه‌هايي که برهم‬

‫کنش‌های سیستم خود را برای تسهیلت آن محدود مي‌کنند‪ ،‬مي‌توانند به سهولت انتقال يابند‪.‬‬

‫مثالهايي که ما برای اين فصل انتخاب کرده‌ايم ‪ ،‬دارای يك ويژگي مشترك مي‌باشند ‪ :‬آنها ابزار کوچکي هستند که ما از آنها به طور‬

‫منظم استفاده مي‌کنیم‪ ،‬اما بخشي از ويرايش هفتم نبودند‪ .‬اگر سیستم شما دارای برنامه‌های مشابه باشد‪ ،‬شما مي‌توانید از آن به عنوان‬

‫يك آگاه کننده برای مقايسه طرحها استفاده کنید‪ .‬و اگر آنها برای شما جديد باشند‪ ،‬شما آنها را به عنوان ابزاری مفید مي‌يابید‪ .‬در هر‬ ‫حال‪ ،‬آنها بايد در روشن کردن اين نکته که هیچ سیستمي کامل نیست و اينکه اغلب توسعه دادن چیزها و فائق آمدن بر کمبودها با‬

‫تلش نه چندان زياد آسان است‪ ،‬به شما کمك کنند‪.‬‬

‫‪ 1‬ت‪ 7 ‬ت‪ ‬ورودي‪ ‬و‪ ‬خروجي‪ ‬استاندارد‪vis : ‬‬ ‫بسیاری از برنامه‌ها ‪ ،‬فقط يك ورودی را مي‌خوانند و يك خروجي را مي‌نويسند ‪ :‬برای چنین برنامه‌هايي ‪ I / O ،‬که فقط از ورودی‬ ‫ل مناسب باشد و تقريباً همیشه برای شروع کار‪ ،‬کافي است ‪.‬‬ ‫استاندارد و خروجي استاندارد استفاده مي‌کند‪ ،‬مي‌تواند کام ً‬

‫اکنون اين مورد را با يك برنامه با عنوان ‪ vis‬شرح مي‌دهیم که ورودی استاندارد خود را برای خروجي استاندارد خود کپي مي‌کند‪ ،‬به‬


‫محیط برنامه سازی لینوکس‬

‫‪186/322‬‬

‫استثنای اينکه اين برنامه ‪ ،‬همه کاراکترهای غیرچاپي را با چاپ کردن آنها به صورت ‪ nnn 1‬مرئي مي‌سازد‪ ،nnn ،‬ارزش هشت هشتي‬ ‫کاراکتر مي‌باشد‪ Vis .‬برای آشکارسازی کاراکترهای عجیب يا کاراکترهای ناخواسته که ممکن است درون فايلها نفوذ کرده باشند‪،‬‬ ‫بي‌ارزش مي‌باشد‪ .‬برای نمونه‪ ، vis ،‬هر پس برد را به صورت ‪ 1010‬پرينت مي‌کند که ارزش هشت هشتي کاراکتر پس برد مي‌باشد ‪:‬‬

‫‪$‬‬

‫‪cat x‬‬

‫‪a b c‬‬ ‫‪$ vis sx‬‬ ‫ ‪a b c \ 01010101010 - -‬‬‫‪$‬‬ ‫برای پويش فايلهای متعدد با اين نسخه ابتدايي از ‪ ، vis‬شما مي‌توانید از ‪ cat‬برای جمع کردن فايلها استفاده کنید ‪:‬‬

‫و در نتیجه از يادگیری چگونگي دستیابي به فايلها از يك برنامه اجتناب کنید‪.‬‬

‫‪$ cat file1 file 2 … ?| vis‬‬ ‫……‬ ‫‪$ cat file1 file 2 … | vis | grep′ \ \ ′‬‬

‫در ضمن ‪ ،‬بايد مشاهده شود که شما مي‌توانید اين کار را با ‪ sed‬انجام دهید‪ .‬چون فرمان ‘‪ ، ’l‬کاراکترهای غیر قابلچاپ را در يك شکل‬

‫قابل فهم آشکار مي‌سازد ‪:‬‬

‫ل واضح‌تر از ‪ vis‬مي‌باشد‪ .‬اما ‪ sed‬هرگز برای فايلهای غیرمتني معني نمي‌دهد‪:‬‬ ‫خروجي ‪ .sed‬احتما ً‬

‫‪$ sed - n 1 x‬‬ ‫‪abc <<<--‬‬‫‪$‬‬

‫‪$ sed - n | / usr / you / bin‬‬ ‫‪$‬‬ ‫! ‪Nothing at all‬‬ ‫(اين برنامه بر روی يك ‪ PDP – 11‬قرار دارد ؛ روی يك سیستم ‪ VAX‬و ‪ sed‬خاموش مي‌شود‪ ،‬احتمال ً به دلیل اينکه ورودی شبیه‬

‫يك سطر خیلي طولني از متن به نظر مي‌رسد)‪.‬‬

‫بنابراين ‪ sed‬نامناسب است و ما مجبور هستیم که يك برنامه جديد بنويسیم‪ .‬ساده‌ترين برنامه‌های کار ورودی و خروجي‪ getchar ،‬و‬

‫‪ putchar‬نامیده مي‌شوند‪ .‬هر فراخواني برای ‪ ،getchar‬کاراکتر بعدی را از ورودی استاندارد مي‌گیرد‪ ،‬که ممکن است يك فايل يا يك‬ ‫لوله و يا يك پايانه (پیش فرض) باشد ـ برنامه‪ ،‬نمي‌داند که کدام يك مي‌باشد ـ متشابها ً ‪ ، )putchar ) C‬کاراکتر ‪ C‬را روی خروجي‬

‫استاندارد قرار مي‌دهد که بر طبق پیش فرض‪ ،‬نیز يك پايانه مي‌باشد‪.‬‬

‫تابع ‪ ، )print f )3‬تبديل فرمت خروجي را انجام مي‌دهد‪ .‬فراخواني‌های ‪ printf‬و ‪ putchar‬مي‌توانند در هر ترتیبي ‪ ،‬يکي در میان‬

‫شوند؛ خروجي‪ ،‬در ترتیب فراخواني‌ها آشکار مي‌شود‪ .‬يك تابع ديگر با عنوان ‪ )scan f )3‬برای تبديل فرمت ورودی وجود دارد؛ اين‬ ‫تابع ورودی استاندارد را مي‌خواند و آنها را به رشته‌ها‪ ،‬اعداد و غیره در جايي که لزم مي‌باشد ‪ ،‬تجزيه مي‌کند ‪ .‬فراخواني ها برای‬ ‫‪ scanf‬و ‪ getchar‬نیز مي‌توانند‪ ،‬با هم مخلوط شوند‪.‬‬ ‫در اين جا اولین نسخه ‪ vis‬عبارت است از ‪:‬‬

‫‪/ * vis : make funny characters visible )version \( * /‬‬ ‫‪# include‬‬ ‫‪< stdio . hs‬‬ ‫‪# include‬‬ ‫‪< stype. hs‬‬ ‫(‬

‫) ‪main‬‬ ‫}‬


‫محیط برنامه سازی لینوکس‬

‫‪187/322‬‬

‫(( ‪′‬‬

‫; ‪int c‬‬ ‫‪while‬‬ ‫(( ) ‪)) ) = getchar‬‬ ‫(‪! = EOF‬‬ ‫‪if )isascii ) c ( $$‬‬ ‫| | ‪) isprint ) c( | | c = = ′ \ n ′‬‬ ‫‪c = = ′ \ t′ | | ′‬‬ ‫; ( ‪put char ) c‬‬ ‫‪else‬‬ ‫; (‪print f ) ″ \ \ % ‘ 30 ″ , c‬‬ ‫‪°‬‬ ‫; ( ) ‪exit‬‬

‫{‬ ‫‪ ، get char‬بايت بعدی يا ارزش ‪ EOF‬را از ورودی‪ ،‬بر مي‌گرداند‪ ،‬زماني که به پايان فايل (يا به يك اشتباه) برخورد مي‌کند‪ .‬در ضمن‪،‬‬

‫‪ EOF‬يك بايت از فايل نمي‌باشد؛ بحث و بررسي مربوط به پايان فايل را در فصل ‪ 2‬به خاطر بیاوريد‪ .‬ارزش ‪ EOF‬به گونه‌ای متفاوت‬ ‫از هر ارزشي که در يك بايت تنها رخ مي‌دهد‪ ،‬تضمین مي‌شود‪ ،‬بنابراين ‪ ،‬میتواند متمايز از داده‌های واقعي باشد ؛ ‪ C‬به صورت ‪int‬‬

‫اعلن مي‌شود و نه ‪ .char‬بنابراين‪ ،‬به اندازه کافي برای حفظ ارزش ‪ EOF‬بزرگ مي‌باشد ‪ .‬سطر‬ ‫بايد در آغاز هر فايل مبدأ ظاهر شود‪ .‬اين سطر باعث مي‌شود که کامپايلر‪ ،‬يك فايل عنوان‬

‫> ‪include < stdio.h‬‬

‫‪#‬‬

‫( ‪ )usr / include / stadio.h/‬از برنامه‌های کاری استاندارد و سمبل‌هايي را بخواند که شامل تعريف ‪ EOF‬مي‌باشند‪ .‬ما از > ‪stadio.‬‬

‫‪ < h‬به عنوان يك صورت مختصر برای اسم کامل فايل در متن استفاده مي‌کنیم‪.‬‬

‫فاي ل > ‪ . < ctype . h‬فايل عنوان ديگری د ر ‪ usr / include /‬مي‌باشد که آزمونهای وابسته به ماشین را برای تعیین ويژگیهای‬

‫کاراکترها تعريف مي‌کن‪ .‬ما در اينجا از ‪ isascii‬و ‪ ، isprint‬برای تعیین اينکه آيا کاراکتر ورودی ‪( Ascll ،‬يعني دارای ارزش کمتر از‬ ‫‪ )0200‬و قابل چاپ مي‌باشد يا نه‪ ،‬استفاده کرديم؛ ساير آزمونها در جدول ‪ 1‬ـ ‪ 6‬فهرست‌وار بیان مي‌شوند‪ .‬توجه داشته باشید که سطر‬

‫جديد جدول‌بندی و فاصله ‪ ،‬توسط تعاريف موجود در > ‪ < ctype . b‬قابل چاپ نیستند‪.‬‬

‫فراخواني ‪ exit‬در انتهای ‪ ،vis‬برای انجام کار برنامه به طور صحیح‪ ،‬ضروری نیست‪ ،‬اما اطمینان مي‌دهد که هر شماره گیرنده از برنامه با‬

‫يك وضعیت خروج نرمال (به صورت قراردادی صفر) از برنامه مواجه مي‌شود زماني که کامل مي‌شود يك روش ديگر برای بازگرداندن‬ ‫وضعیت‪ ،‬خارج شدن از ‪ main‬با ‪ return o‬مي‌باشند ارزش بازگشت از ‪ ،main‬وضعیت خروج برنامه مي‌باشد‪ .‬اگر ‪ return‬يا ‪ exit‬به‬

‫صورت آشکار وجود نداشته باشد‪ ،‬وضعیت خروج ‪ ،‬غیر قابل پیش‌بیني است‪.‬‬

‫برای کامپايل کردن يك برنامه ‪ ، C‬مبدأ را در فايلي قرار دهید که نام آن با ‪ .C‬پايان مي‌يابد‪ ،‬مانند ‪ ، vix.c‬آن را با ‪ cc‬کامپايل کنید‪،‬‬

‫سپس نتیجه را اجرا کنید که به اين صورت کامپايلر در يك فايل با عنوان ‪ a.out‬باقي مي‌ماند‪ ’a‘ ( .‬برای اسمبلر مي‌باشد) ‪:‬‬

‫‪$ cc vis . c‬‬ ‫‪$ a .out‬‬ ‫‪hello‬‬ ‫‪world ctl-g‬‬ ‫‪helo‬‬ ‫‪world \ 007‬‬ ‫‪ctl – d‬‬ ‫‪$‬‬ ‫در حالت عادی شما بايد ‪ a.out‬را مجدداً نامگذاری کنید‪ .‬زمای که کار مي‌کند و يا از انتخاب –‪ o‬از ‪ cc‬برای انجام آن به طور مستقیم‬

‫استفاده کنید ‪:‬‬


‫محیط برنامه سازی لینوکس‬

‫‪188/322‬‬

‫‪output in vis not a .out‬‬ ‫خروجي در ‪ vis، a.out‬نمي‌باشد‪.‬‬

‫‪vis . c‬‬

‫‪cc – o vis‬‬

‫‪$‬‬

‫تمرين ‪ 1‬ت ‪ .6‬ما تصميم گرفتيم كه جدول‌بندي‌ها بايد كنار گذاشته شوند‪ ،‬به جاي اينكه به‬ ‫صورت \ ‪ t‬يا ‪ ‬يا \ ‪ 011‬آشكار شوند‪ ،‬چون استفاده مهم ما از ‪ ، vis‬پيدا كردن كاراكترهاي‬ ‫حقيقتاً نامبهم مي‌باشد تتت تجدول‌بنديها ‪،‬ت غيرتصويري‌ها‪ ،‬فاصله‌ها در انتهاي سطرها تو‬ ‫غيره‪ Vis .‬را به گونه‌اي تغيير دهيد كه كاراكترهايي شبيه جدول‌بندي‪ ،‬پس كج خط ‪ ،‬پس‬ ‫برد‪ ،‬كاغذ ت خورد و غيره‪ ،‬در اجراهاي قراردادي ‪ c‬خود \ ‪ t ، \ \ ، \ b ، \ f‬و غيره‪ .‬پرينت‬ ‫شوندت توت تدرت تنتيجهت تفاصله‌هاي تخاليت تدرت تانتهايت تسطرهات تعلمت‌گذاري تشوند‪ .‬آيات تشما‬ ‫ميتوانيد چنين كاري را بدون ابهام انجام دهيد؟ طرح خود را با ‪ sed - n 1 $‬مقايسه كنيد‪.‬‬ ‫تمرين ‪ 2‬ـ ‪ Vis .6‬را به گونه‌ای تغییردهید که سطرهای بلند را در طول معقول تاکند‪ .‬اين کار چگونه با خروجي غیر مبهم مورد نیاز در‬

‫تمرين قبلي برهم کنش مي‌کند؟‬

‫‪ 2‬ت‪6  ‬ت‪ ‬آرگومانهاي‪ ‬برنامه‪ : ‬نسخة‪vis  2  ‬‬ ‫زماني که يك برنامه ‪ c‬اجرا مي‌شود‪‌ .‬آرگومانهای سطر فرمان‪ ،‬به عنوان يك شماره ‪ argc‬و يا آرايه ‪ argv‬از اشاره‌گرها‪ ،‬برای رشته‌های‬ ‫کاراکتری که شامل آرگومانها مي‌باشند در دسترس تابع ‪ main‬قرار مي‌گیرند‪ .‬بر طبق قرارداد ‪ ]argv ]0 ،‬خودش اسم فرمان است‪،‬‬ ‫بنابراين ‪ argc ،‬همیشه بزرگتر از صفر است؛ آرگومانهای مفید ‪ ] argv ]1[ … argv ] g r g c - 1‬هستند‪ .‬به خاطر داشته باشید که‬

‫جهت دهي مجدد باـ < وـ > ‪ ،‬توسط شل انجام مي‌شود و نه توسط برنامه‌های منفرد‪ ،‬بنابراين جهت‌دهي مجدد تأثیری بر تعداد‬ ‫آرگومانهای مشاهده شده توسط برنامه ندارد‪.‬‬

‫برای شروع عملکرد يا آرگومان‪ ،‬با افزودن يك آرگومان انتخابي ‪ vis‬را تغییر مي‌دهیم ‪ ، vis-s :‬همه کاراکترهای غیر چاپي را خارج‬

‫مي‌کند به جای اينکه آنها را به طور مداوم نمايش دهد‪ .‬اين انتخاب‪ ،‬برای پاك کردن فايلها از ساير سیستم‌ها مناسب است‪ ،‬برای مثال‪،‬‬

‫سیستم هايي که از ‪( CRLF‬سطر خورد و سطر جديد) به جای يك سطر جديد به سطرها پايان مي‌دهند‪.‬‬ ‫‪*/‬‬

‫(کاراکترهای جالب را آشکار مي‌سازد (نسخه ‪/ * vis : 2‬‬

‫> ‪# include < stadio . b‬‬ ‫> ‪# inclue < stype . h‬‬ ‫(‪main )argc , argv‬‬ ‫; ‪int argc‬‬ ‫; [ ] ‪char * argv‬‬ ‫}‬ ‫; ‪int c , strip = 0‬‬

‫‪if cargc > 1 & $ strcmp )argv ] 1 [ , ″ - s ″( = = 0‬‬ ‫; ‪strip = 1‬‬ ‫(‪while )) c – getcharc )1‬‬ ‫( ‪! = EOF‬‬


‫محیط برنامه سازی لینوکس‬

‫‪189/322‬‬

‫‪if )isassiicc( $ $,‬‬ ‫(( ‘ ‪) isprintcc( | | c = = ′ \ n ′ | | c = = ′ \ t′ | | c = ′‬‬ ‫; (‪putchar ) c‬‬ ‫(‪else if ) ! strip‬‬ ‫; (‪print f ) ″ \ \ % 30″ , c‬‬ ‫; (‪exit )0‬‬ ‫{‬

‫جدول ‪ 6‬ـ ‪ 1‬ـ درشت ـ دستورالعملهاي آزمون کاراکتر <‪> ctype.b ‬‬ ‫الفبايي ‪A-Z ، a-z :‬‬

‫‪) isalpha )c‬‬

‫مورد باليي ‪A – Z :‬‬

‫‪) isupper )c‬‬

‫مورد پائین ‪a – z :‬‬

‫‪) islower ) c‬‬

‫رقم ‪ 9 :‬ـ ‪0‬‬

‫‪) isdigit ) c‬‬

‫رقم شانزده شانزدهي‪ 9 :‬ـ ‪0‬‬

‫‪A–F‬‬

‫‪a–f‬‬

‫الفبايي يا رقم‬

‫‪)isalnum ) c‬‬

‫فاصله‪ ،‬جدول‌بندی‪ ،‬سطر جديد‪ ،‬جدول بندی عمودی‪ ،‬کاغذ ـ خورد ‪ ،‬بازگشت‬

‫غیر الفبايي ـ عددی‪ ،‬يا کنترل يا فاصله‬ ‫قابل چاپ ‪ :‬هر تصويری‬ ‫کاراکتر کنترل ‪:‬‬ ‫کاراکتر = < ‪c‬‬

‫‪) isxdigit ) c‬‬

‫‪) ispunct ) c‬‬ ‫‪) isprint ) c‬‬

‫‪c || 040 c < = 0 < = = 0177‬‬ ‫= < ‪0177 0‬‬

‫‪) isspace ) c‬‬

‫‪Ascl :‬‬

‫‪iscntrl )c‬‬

‫)‬

‫‪isascii )c‬‬

‫)‬

‫‪، argv‬ت تيكت تاشاره‌گرت تبهت تآرايه‌ايت تاستت تكهت تعناصرت تمنفردت تآنت تاشاره‌گرهاييت تبهت تآرايه‌هاي‬ ‫كاراكترها تمي تباشند؛‌ت هر تآرايه‪،‬ت تبات تكاراكترت ‪ NUL‬ازت ‪ )Ascll )′10 ′‬پايان تمي‌پذيرد‪ ،‬تبنابراين‬ ‫مي‌تواند به صورت يك رشته عمل كند‪ .‬اين نسخه ازت ‪ ، vis‬با كنترل اينكه آيا يك آرگومان‬ ‫وجود دارد يا نه و آيا – ‪ s‬مي‌باشد يا نه‪ ،‬آغاز مي‌كند‪.‬‬ ‫(آرگومانهای غیر معتبر ناديده گرفته مي‌شوند)‪ .‬تابع (‪ ، strcmp )3‬دو رشته را مقايسه مي‌کند‪ ،‬و اگر آنها شبیه به هم باشند‪ ،‬صفر را بر‬ ‫مي‌گرداند‪.‬‬

‫جدول ‪ 2‬ـ ‪ . 6‬يك مجموعه از تابع‌ها را با استفاده کلي و به کارگیری رشته‪ ،‬فهرست‌بندی مي‌کند‪ ،‬که يکي از آنهاه ‪ strmp‬مي‌باد‪.‬‬

‫معمول ً استفاده از اين تابع‌ها‪ ،‬به جای نوشتن تابعهای خود‪ ،‬بهترين راه مي باشد‪ ،‬چون آنها استاندارد هستند‪ ،‬آنها بدون خطا هستند و‬

‫آنها اغلب سريعتر از چیزی هستند که شما خودتان مي‌توانید بنويسید‪ ،‬چون آنها برای ماشین‌های خاص ‪ ،‬مطلوب شده‌اند (گاهي اوقات‬ ‫‪ ،‬با نوشته شدن در زمان اسمبلي مطلوب مي‌باشند)‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪190/322‬‬

‫تمرين ‪ 3‬ـ ‪ . 6‬آرگومان – ‪ s‬را به گونه‌ای تغییر دهید که ‪ vis – sn‬فقط رشته‌های ‪ n‬يا کاراکترهای پیاپي قابل چاپ را پرينت کند‪،‬‬ ‫کاراکترهای غیرچاپي را حذف کند و توالیهای کاراکترهای قابل چاپ را کوتاه کند ‪ .‬چنین چیزی برای جدا کردن بخشهای بعدی‬

‫فايلهای غیر متني مانند برنامه‌های قابل اجرا ارزشمند مي‌باشد‪ .‬بر فراز نسخه‌های سیستم‪ ،‬يك برنامه ‪ string‬را تهیه مي‌کنند که چنین‬ ‫کاری را انجام مي‌دهد‪ .‬آيا داشتن يك برنامه مجزا يا يك آرگمان برای ‪ vis‬بهتر است‪.‬‬

‫تمرين ‪ 4‬ـ ‪ .6‬در دسترس بودن کد مبدأ ‪ c‬يکي از نقاط قوت سیستم يونیکس مي‌باشد ـ کد ‪ ،‬راه‌حلهای ظريف را برای بسیاری از‬

‫مشکلت برنامه‌نويسي شرح مي‌دهد‪ .‬موازنة بین قابلیت خوانده شدن مبدأ ‪ c‬و بهینه سازی اتفاقي دست آمده از نوشتن مجدد به زبان‬ ‫اسمبلي را شرح دهید‪.‬‬

‫جدول ‪ 2‬ـ ‪ 6‬ـ تابعهاي استاندارد رشته‬ ‫رشته ‪ t‬را به رشتة ‪ s‬پیوست مي‌دهد؛ ‪ s‬را بر مي‌گرداند‬

‫‪)stract )s , t‬‬

‫اکثر کاراکترهای ‪ n‬از ‪ t‬را به ‪ s‬ضمیمه مي‌کند‬

‫‪)strnact )s , t , n‬‬

‫‪ t‬را برای ‪ s‬کپي مي‌کند؛ ‪ s‬را بر مي‌گرداند‬

‫‪)strcpy )s , t‬‬

‫دقیق ًا کاراکترهای ‪ n‬را کپي مي‌کند؛ اگر لزم باشد ‪ pad‬را خالي مي‌کند‬

‫‪ s‬و ‪ t‬را مقايسه مي‌کند ‪ < , 0 ،‬و > ‪ 0‬را برای دو = = > ‪ ,‬برمي‌گرداند‬ ‫اکثر کاراکترهای ‪ n‬را مقايسه مي‌کند‬

‫‪)strncpy )s , t , n‬‬ ‫‪)strcmp )s , t‬‬ ‫‪)strncmp )s , t ,n‬‬

‫طول ‪ s‬را بر مي‌گرداند‬

‫‪)strlen )s‬‬

‫اشاره‌گر را به اولین ‪ c‬در ‪ s‬بر مي‌گرداند‪ ،‬اگر ‪ Null‬نباشد‬

‫‪)strchr )s , c‬‬

‫اشاره‌گر را به‌آخرين ‪ c‬در ‪ s‬بر مي‌گرداند‪ ،‬اگر ‪ null‬نباشد‬

‫‪)strrchr )s , c‬‬

‫اينها‪ index ،‬و ‪ rindex‬بر روی سیستم‌های قبلي هستند‬

‫ارزش عدد صحیح ‪ s‬را بر مي‌گرداند‬

‫‪)atoi )s‬‬

‫ارزش مییز شناور ‪ s‬را بر مي‌گرداند؛‬

‫‪)atof )s‬‬

‫مستلزم اعلن ‪ )atof )s‬دوگانه مي‌باشد‪.‬‬

‫اشاره‌گر را به بايتهای ‪ n‬از حافظه برمي‌گرداند‪ ،‬اگر ‪ null‬نتواند‬

‫‪)malloc )n‬‬

‫اشاره‌گر را به بايتهای ‪ nxm‬برمي‌گرداند‪ ،‬برای صفر تنظیم مي‌کند‬

‫‪)calloc )n,m‬‬

‫اگر ‪ null‬نتواند‪ Malloc .‬و ‪ * calloc ، char‬را بر مي‌گردانند‬ ‫حافظه آزاد تخصیص يافته توسط ‪ malloc‬يا ‪calloc‬‬ ‫‪ 3‬ت‪ 6 ‬ت‪ ‬دستيابي‪ ‬به‪ ‬فايل‪ : ‬نسخه‪3 ‬‬

‫‪free )p‬‬

‫)‬

‫‪vis‬‬

‫دو نسخه اول ‪ ،vis‬ورودی استاندارد را مي‌خوانند و خروجي استاندارد را مي‌نويسند‪ ،‬و هردو از شل منتج مي‌شوند‪ .‬مرحله بعدی‪ ،‬تغییر‬

‫‪ vis‬برای دستیابي به فايلها از طريق اسامي آنها است‪ .‬بنابراين‬


‫محیط برنامه سازی لینوکس‬ ‫‪$‬‬

‫‪191/322‬‬

‫‪… vis file 1 file 2‬‬

‫فايلهای نامگذاری شده را به جای ورودی استاندارد‪ ،‬پويش مي‌کند‪ .‬اگر چه آرگومانهای اسم فايل شايد وجود نداشته باشند اما ما‬

‫مي‌خواهیم ‪ ، vis‬ورودی استاندارد خود را بخواند‪ .‬سوال اين است که چگونه فايلها را برای خوانده شدن مرتب کنیم ـ يعني اينکه ‪،‬‬

‫چگونه اسامي فايلها را به بیان‌های ‪ I /O‬متصل کنیم که دقیق ًا داده‌ها را بخوانند‪.‬‬

‫قواعد ساده هستند‪ .‬قبل از اينکه يك فايل بتواند خوانده يا نوشته شود‪ ،‬بايد توسط تابع کتابخانه استاندارد يعنيـ ‪ Fopen‬باز شود‪.‬‬

‫‪ ،Fopen‬يك اسم فايل را مي‌گیرد (همانند ‪ temp‬يا ‪ ، )etc / passwd‬سیستم‌داری و انتقال را با کرنل انجام مي‌دهد و يك اسم دروني‬ ‫را که بايد در عملکردهای بعدی روی فايل استفاده شود ‪ ،‬بر مي‌گرداند‪.‬‬

‫اين نام دروني‪ ،‬دقیقا ً يك اشاره‌گر مي‌باشد که اشاره‌گر فايل نام دارد‪ ،‬برای ساختاری که شامل اطلعاتي در مورد فايل مي‌باشد‪ ،‬مانند‬

‫مکان يك میانگیر ‪ ،‬موقعیت کاراکتر فعلي در میانگیر‪ ،‬و اينکه آيا يك فايل خوانده يا نوشته مي‌شود و مواردی از اين قبیل‪ .‬يکي از‬

‫تعاريف بدست آمده از طريق > ‪ ، <stdio.b‬برای يك ساختار مي‌باشد که ‪ FILE‬نام دارد‪ .‬اعلن برای يك اشاره‌گر فايل عبارت است‬ ‫از‬

‫; ‪FILE * fp‬‬ ‫اين اعلن بیان مي‌کند که ‪ fp‬يك اشاره‌گر به يك ‪ FILE‬مي‌باشد‪ Fopen .‬يك اشاره‌گر را به يك ‪ FILE‬بر مي‌گرداند؛ يك نوع اعلن‬ ‫برای ‪ fopen‬در > ‪ <stdio. b‬وجود دارد‪.‬‬

‫فراخاني واقعي برای ‪ fopen‬در يك برنامه عبارت است از‬

‫‪chr‬‬

‫; ‪* name , * mode‬‬ ‫اولين آرگومان ‪ ، Foppen‬نام فايل‪ ،‬به عنوان يك رشته كاراكتر مي‌باشد‪ .‬دومين آرگومان‪ ،‬نيز‬

‫يك رشته كاراكتر مي‌باشد و نشان مي‌دهد كه شما چگونه از فايل استفاده مي‌كنيد و‬ ‫روشهاي مجاز‪ ،‬خواندن ( ‪ ، ) ″r″‬نوشتن ( ‪ ) ″w″‬يا ضميمه كردن ( ‪ ) ″a″‬مي‌باشند‪.‬‬

‫اگر فايلي که شما برای نوشتن يا ضمیمه کردن باز مي‌کنید‪ ،‬وجود نداشته باشد ‪ ،‬اگر امکان‌پذير باشد‪ ،‬بوجود مي‌آيد‪ .‬باز کردن يك فايل‬ ‫موجود برای نوشتن باعث مي‌شود که محتواهای قبلي ‪ ،‬حذف شوند‪ .‬تلش برای خواندن فايلي که وجود ندارد‪ ،‬يك خطا است و‬

‫همانند تلش برای خواندن يا نوشتن يك فايل مي‌باشد زماني که شما اجازه نداريد‪ .‬اگر خطايي وجود داشته باشد‪ ، fopen ،‬ارزش‬ ‫ل به صورت (‪ )* char‬در > ‪ <stdio . h‬تعريف مي‌شود)‪.‬‬ ‫اشاره‌گر بي‌اعتبار را به صورت ‪( null‬تهي) بر مي‌گرداند‪( .‬که معمو ً‬

‫مورد بعدی مورد نیاز ‪ ،‬روش خواندن يا نوشتن فايل مي‌باشد زماني که باز مي‌شود امکانات متعددی برای اين مورد وجود دارند ‪ ،‬که از‬ ‫آنها ‪ getc‬و ‪ ، putc‬ساده‌ترين هستند‪ ،getc .‬کاراکتر بعدی را از فايل مي‌گیرد‪.‬‬

‫‪)C = getc )fp‬‬

‫کاراکتری بعدی از فايل را که به عنوان ‪ fp‬به آن استناد مي‌شود در ‪ c‬قرار مي‌دهد؛ و ‪ EOF‬را برمي‌گرداند‪ ،‬زمني که به انتهای فايل‬ ‫مي‌رسد‪ ، Putc .‬شبیه به ‪ getc‬مي‌باشد ‪:‬‬

‫‪)putc ) c , fp‬‬ ‫کاراکتر ‪ c‬را بر روی فايل ‪ fp‬قرار مي‌دهد و ‪ c‬را برمي‌گرداند‪ getc .‬و ‪ putc ، EOF‬را برمي‌گردانند‪ ،‬اگر يك اشتباه رخ دهد‪.‬‬

‫زماني که يك برنامه آغاز مي‌شود‪ ،‬سه فايل باز مي‌شوند و اشاره‌گرهای فايل برای آنها تهیه مي‌شوند‪ .‬اين فايلها‪ ،‬ورودی استاندارد ‪،‬‬ ‫خروجي استاندارد و خروجي خطای استاندارد هستند؛ اشاره‌گرهای فايل مربوطه‪،‬ـ ‪ stdin ، stdout‬وـ ‪ stderr‬نامیده مي‌شوند‪ .‬اين‬

‫اشاره‌گرهای فايل در‬

‫> ‪ ، < stdio . h‬اعلن مي‌شوند؛ آنها مي‌توانند در هر جايي استفاده شوند که به همان منظور تايپ ‪ ، * FILE‬مي‌تواند استفاده شود‪ .‬اما‬


‫محیط برنامه سازی لینوکس‬

‫‪192/322‬‬

‫آنها ثابت‌ها هستند و نه متغیرها‪ ،‬بنابراين شما نمي‌توانید‪ ،‬به آنها استناد کنید‪.‬‬

‫‪ ، ) ( getchar‬همانند ‪ )getc )stdin‬میباشد و ‪ ) putchar )c‬همانند ‪ )putc c , stdout‬مي‌باشد‪ .‬در حقیقت ‪ ،‬هر چهار تابع‪ ،‬به عنوان‬

‫> ‪ < stdio . h‬تعريف مي‌شوند‪ ،‬چون آنها با اجتناب از‬

‫يك يك تابع برای هر کاراکتر ‪ ،‬سريعتر اجرا مي‌کنند‪ .‬به جدول ‪ 3‬ـ ‪ 6‬برای ساير تعاريف در‬ ‫> ‪ <stdio . h‬مراجعه کنید‪.‬‬

‫با برخي از مقدمات خارج از روش ‪ ،‬اکنون ما مي‌توانیم سومین نسخه از ‪ vic‬را بنويسیم‪ .‬اگر آرگومانهای سطر فرمان وجود داشته‬

‫باشند‪ ،‬آنها به ترتیب پردازش مي‌شوند‪ .‬اگر آرگومانها وجود نداشته باشند‪ ،‬ورودی استاندارد پردازش مي‌شود‪.‬‬

‫‪/ * vis : make funny characters visible )version 3( * /‬‬

‫> ‪# include < stdio . b‬‬ ‫> ‪# include < type . b‬‬ ‫; ‪int strip = 0‬‬ ‫*‪/‬‬ ‫‪1 ⇒ discarc special characters * /‬‬ ‫(‪main )argc , argv‬‬ ‫; ‪int argc‬‬ ‫; [ ] ‪char * argv‬‬ ‫}‬ ‫; ‪int i‬‬ ‫; ‪FILE * FP‬‬ ‫} (‪While )argc > 1 $ $ argv ]1[ ]0[ = = ′- ′‬‬ ‫} ( [‪Switch )argv ]1[ ]1‬‬ ‫‪case ′ s ′ :‬‬ ‫‪/ * - s ; strip funny chars * /‬‬ ‫; ‪strip = 1‬‬ ‫; ‪break‬‬ ‫‪default :‬‬ ‫‪fprintf )stderr , ″ % s : unknown arg % s \ n ″,‬‬ ‫; ‪argv ] 0[ , argv ]1[1‬‬ ‫;(‪exit )1‬‬ ‫{‬ ‫; ‪argc - -‬‬ ‫; ‪argv + +‬‬ ‫{‬ ‫(‪if )argc = = 1‬‬ ‫;(‪vis )stdin‬‬ ‫‪else‬‬ ‫( ‪for ) i = l ; i < argc ; i + +‬‬ ‫} (‪if )) fp = fopen )argv ]i[ , ″r″ (( = = NULL‬‬ ‫‪fprintf )stderr , ″ % s : can’t open % s \ n″ ,‬‬ ‫;( [‪argv ]0[ , argv ] i‬‬ ‫; (‪exit )1‬‬ ‫} ‪{ else‬‬ ‫; (‪vis )fp‬‬ ‫; (‪fclose )fp‬‬ ‫{‬


‫محیط برنامه سازی لینوکس‬

‫‪193/322‬‬

‫; (‪exit )0‬‬

‫{‬ ‫اين رمز ‪ ،‬بر اين قرارداد تکیه دارد که آرگومانهای اختیاری در ابتدا مي‌آيند‪ .‬پس از اينکه هر آرگومان اختیاری‪ ،‬پردازش مي‌شود‪ argc ،‬و‬

‫‪ argv‬تنظیم مي‌شوند‪ ،‬در نتیجه مابقي برنامه‪ ،‬وابسته به حضور آن آرگومان نمي‌باشد‪ .‬اگرچه ‪ ،vis‬فقط انتخاب تنها را تشخیص مي‌دهد‪،‬‬ ‫اما ما رمز را به صورت يك حلقه برای نشان دادن راه برای تشخیص پردازش آرگومان نوشتیم‪ .‬در فصل ‪ 1‬ما روش نامقطعي را که بر‬

‫طبق آن برنامه‌های يونیکس از آرگومانهای انتخابي استفاده مي‌کردند توضیح داديم‪ .‬جدای از يك میل برای بي‌نظمي‪ ،‬يکي از دليل آن ‪،‬‬

‫اين است که نوشتن رمز برای استفاده از بخش آرگومان برای هر تغییر‪ ،‬به طور بديهي آسان نمي‌باشد‪ .‬تابع (‪ get opt )3‬که بر روی‬ ‫برخي از سیستم‌ها يافت مي‌شود‪ .‬يك تلش برای توجیه کردن موقعیت مي‌باشد؛ شما بايد قبل از نوشتن برنامه خود ‪ ،‬به تحقق در مورد‬

‫آن بپردازيد‪.‬‬

‫برنامه کار ‪ ، ris‬يك فايل منفرد را پرينت مي‌کند ‪:‬‬

‫(( ‪′‬‬

‫‪vis )fp( / * make chars visible in FILE * fp * /‬‬ ‫; ‪FILE * Fp‬‬ ‫}‬ ‫; ‪int c‬‬ ‫(‪while )) c = get c )fp( ! = EOF‬‬ ‫‪if )isaciicc( $$‬‬ ‫‪) isprint )c ( | | c = = ′ \n | | c = = ′ \ t′ / | c = = ′‬‬ ‫; ( ‪put cahr ) c‬‬ ‫(‪elw if ) ! strip‬‬ ‫; ( ‪printf ) ″ \ \ % 30 ″ , c‬‬ ‫{‬

‫تابع ‪ fprintf‬مشابهه با ‪ printf‬مي‌باشد‪ ،‬به جز برای يك آ‌رگومان نشان‌‌گر فايل‪ ،‬که فايلي را که بايد نوشته شود مشخص مي‌کند‪.‬‬

‫تابع ‪ ،fclose‬ارتباط بین اشاره‌گر فايل و نام خروجي را که توسط ‪ Fopen‬تعیین شد‪ ،‬از بین مي‌برد و اشاره‌گر فايل را برای فايل ديگر‬ ‫آزاد مي‌کند‪ .‬چون يك محدوديت بر روی تعداد فايلهايي (حدود ‪ )20‬وجود دارد که يك برنامه مي‌تواند به طور همزمان باز کند‪ ،‬در‬

‫نتیجه‪ ،‬بهترين کار‪ ،‬آزاد کردن فايلها در زماني است که ديگر به آنها نیازی نیست‪ .‬در حالت عادی‪ ،‬خروجي تهیه شده با هر کدام از‬

‫تابعهای کتابخانه استاندارد ‪ ،‬مانند ‪ printf ، putc‬و غیره‪ ،‬میانگیر مي‌سازد‪ ،‬و در نتیجه مي‌تواند به منظور موثر بودن‪ ،‬در ‪ chunk‬های‬ ‫بزرگ نوشته شود‪ ( .‬در اينجا استثنا‪ ،‬خروجي برای يك پايانه مي‌باشد‪ ،‬که معمول ً در همان زماني که تولید مي‌شود‪ ،‬نوشته مي‌شود و يا‬

‫حداقل‪ ،‬زماني که سطر جديد پرينت مي‌شود)‪ .‬فراخواني ‪ fclose‬بر روی يك فايل خروجي نیز هرگونه خروجي میان‌گیر شده را خارج‬ ‫مي‌کند‪ Fclose .‬نیز به طور خودکار برای هر فايل باز‪ ،‬فراخوان مي‌شود زماني که يك برنامه‪ exit ،‬را فرا مي‌خواند و يا ازـ ‪main‬‬ ‫برمي‌گردد‪.‬‬

‫‪ ،Stderr‬به کل برنامه تخصیص داده مي‌شود به همان روشي که ‪ stdin‬و ‪ stdout‬تخصیص داده مي‌شوند‪ .‬خروجي نوشته شده بر روی‬

‫‪ stdder‬بر روی پايانه کاربر ظاهر مي‌شود‪ ،‬حتي اگر خروجي استاندارد مجدداً جهت‌يابي شود‪ ،Vis .‬تشخیص خود را بر روی ‪stderr‬‬

‫به جای ‪ stdout‬مي‌نويسد‪ ،‬بنابراين اگر يکي از فايلها نتواند به دلیلي دستیابي شود‪ ،‬پیغام راه خود را به سمت پايانه کاربر به جای ناپديد‬

‫شدن درون خط لوله‌ای يا درون يك فايل خروجي‪ ،‬پیدا مي‌کند‪( .‬خطای استاندارد‪ ،‬اندکي پس از لوله‌ها‪ ،‬اختراع شد‪ ،‬پس از اينکه‬


‫محیط برنامه سازی لینوکس‬

‫‪194/322‬‬

‫پیغامهای خطا‪ ،‬شروع به ناپديد شدن درون خطوط لوله‌ای کردند)‪.‬‬

‫تا حدوی اختیاری ‪ ،‬ما تصمیم گرفتیم که ‪ vis‬از سیستم خارج میشود اگر نتواند يك فايل ورودی را باز کند؛ چنین چیزی برای برنامه‌ای‬

‫که اغلب به صو رت برهم‌کنشي استفاده مي‌شود و با يك فايل ورودی تنها مي‌باشد‪ ،‬معقول است‪ .‬شما مي‌توانید برای طرح ديگر به‬

‫بحث و بررسي بپردازد‪.‬‬

‫تمرين ‪ 5‬ـ ‪ .6‬يك برنامه ‪ pritable‬بنويسید که نام هر فايل آرگومان را که شامل فقط کاراکترهای قابل چاپ مي‌باشد‪ ،‬پرينت کند؛ اگر‬ ‫فايل شامل کاراکتر غیر قابل چاپ باشد‪ ،‬اسم آن پرينت نشود‪ Printable .‬در موقعیتهايي مانند اين ‪ ،‬مفید است ‪:‬‬

‫‪pr ′ printable * ′ | pr‬‬

‫انتخاب ‪ 7‬ـ را برای معکوس کردن حس آزمون‪ ،‬همانند ‪ grep‬وارد کنید‪.‬‬

‫‪$‬‬

‫‪ Printable‬چه بايد انجام دهد اگر آرگومانهای اسم فايل وجود نداشته باشند؟ ‪ printable‬به چه وضعیتي بايد برگردد؟‬

‫ورودی استاندارد‬

‫جدول ‪ 3‬ـ ‪ 6‬ـ برخي از تعاريف > ‪< stdio . b‬‬ ‫‪stdin‬‬

‫خروجي استاندارد‬

‫‪stdout‬‬

‫خطای استاندارد‬

‫‪stderr‬‬

‫انتهای فايل ‪ :‬در حالت عادی ‪ 1‬ـ‬

‫‪EOF‬‬

‫نشانگر غيرمعتبر ؛ در حالت عادي ‪°‬‬

‫‪NULL‬‬

‫استفاده شده برای اعلن اشاره‌گرهای فايل‬

‫‪FILE‬‬

‫اندازه نرمال میانگر ‪( I / O‬اغلب ‪ 512‬يا ‪)1024‬‬

‫‪BUFSIZ‬‬

‫يك کاراکتر از جريان ‪ FP‬باز مي‌گرداند‬ ‫( ) ‪getchar‬‬

‫کاراکتر ‪ c‬را بر روی رشته ‪ fp‬قرار مي‌دهد‬ ‫( ‪put char ) c‬‬

‫‪)getc )fp‬‬ ‫‪)getc )stdin‬‬ ‫‪)putc )c , fp‬‬ ‫‪)putc ) c , stdout‬‬

‫صفر نمي‌باشد زماني که انتهای فايل بر روی رشته ‪ fp‬قرار دارد‬

‫صفر نمي‌باشد زماني که هر گونه خطا بر روی رشته ‪ fp‬قرار دارد‬

‫توصیف‌گر فايل برای رشته ‪ fp‬؛ به فصل ‪ 7‬مراجعه کنید‬

‫‪)feop )fp‬‬ ‫‪)ferror )fp‬‬ ‫‪)fileno )fp‬‬

‫‪ 4‬ت‪ 6 ‬ت‪ ‬يك‪ ‬چاپگر‪ ‬نمايشي‪ ‬در‪ ‬يك‪ ‬زمان‪P : ‬‬ ‫تاکنون ما از ‪ cat‬برای بررسي فايلها استفاده کرديم‪ .‬اما اگر يك فايل بلند باشد‪ ،‬و اگر شما توسط يك اتصال دارای سرعت بال به سیستم‬ ‫خود متصل شده باشید‪ ،cat ،‬خروجي را به گونه‌ای تولید مي‌کند که بي‌نهايت سريع خوانده شود‪ ،‬حتي اگر شما با ‪ ctl-s‬و ‪ ctl- q‬سريع‬ ‫باشید‪.‬‬

‫به طور آشكارا‪ ،‬بايد يك برنامه براي پرينت يك فايل در ‪chunk‬هاي كوچك قابل كنترل وجود‬ ‫داشته باشد‪ ،‬اما يك برنامه استاندارد وجود ندارد‪ ،‬احتمالً به دليل اينكه سيستم اوليه‬ ‫يونيكس‪ ،‬در روزهاي پايانه‌هاي نسخه سختت (كاغذ) و سطرهاي ارتباطي كند نوشته‬


‫محیط برنامه سازی لینوکس‬

‫‪195/322‬‬

‫شده است‪ .‬بنابراين‪ ،‬مثال بعدي ما برنامه‌اي با عنوان ‪ P‬مي‌باشد كه يك فايل پرده پر را در‬ ‫يك زمان پرينت مي‌كند و منتظر جواب از كاربر‪ ،‬پس از هر پرده نمايش و قبل از رفتن به‬ ‫پرينت بعدي‪ ،‬مي‌ماند‪ ، ″P″( .‬يك اسم كوتاه و مناسب براي برنامه‌اي است كه ما آن را‬ ‫بسيار زياد استفاده مي‌كنيم)‪.‬‬ ‫همانند ساير برنامه‌ها‪ p ‍ ،‬از فايلهای نامگذاری شده به عنوان آرگومانها ويا از ورودی استاندارد خود مي‌خواند ‪:‬‬

‫‪$ p vis . c‬‬ ‫…‬ ‫‪$ grep ′ # define ′ * . ] ch [ | p‬‬ ‫…‬ ‫‪$‬‬

‫اين برنامه ‪ ،‬به بهترني نحو در زبان ‪ c‬نوشته مي‌شود‪ ،‬چون اين برنامه در زبان ‪ c‬آسان است و در زبانهای ديگر دشوار است؛ ابزار‬ ‫استاندارد‪ ،‬در ترکیب کردن ورودی از يك فايل يا لوله با ورودی پايانه‪ ،‬مناسب نیستند‪.‬‬

‫طرح اساسي و بي پيرايه ‪ ،‬چاپ كردن ورودي در قطعه‌هاي كوچك مي‌باشد‪ .‬يك اندازه‬ ‫مناسب براي قطعه‪،‬ت ‪ 22‬سطر مي‌باشدت ‪ :‬كه اين اندازه‪ ،‬اندكي كمتر از پرده نمايشت ‪24‬‬ ‫سطريت تاكثرت تپايانه‌هايت تتصويريت تمي‌باشدت تو ت‬

‫‪1‬‬ ‫‪3‬‬

‫تتازت تيكت تصفحهت تاستاندارد ت ‪ 66‬سطري‬

‫مي‌باشد‪ .‬يك روش ساده تبراي اينكهت ‪ p‬به كاربر پيامواره تبدهد‪ ،‬چاپنكردن آخرين سطر‬ ‫جديد از هر قطعه ‪ 22‬سطري مي‌باشد‪ .‬بنابراين‪ ،‬مكان نما در انتهاي راست هر سطر به‬ ‫جاي حاشيه چپ‪ ،‬مكث مي‌كند‪ .‬زماني كه كاربر كليدت ‪ RETURN‬را فشار مي‌دهد‪ .‬سطر‬ ‫جديد مفقود را ذخيره مي‌كند و بنابراين باعث مي‌شود كه سطر بعدي در مكان صحيح‬ ‫خود تآشكار تشود‪ .‬اگرت تكاربر‪،‬ت ‪ ctl-d‬يات ‪ g‬رات تدرت تانتهاي تيك تپرده تنمايش تتايپ تكند‪،‬ت ‪ p‬بوجود‬ ‫مي‌آيد‪.‬‬

‫ما عملکردهای خاصي را برای سطرهای طولني انجام نمي‌دهیم ما همچنین درخصوص فايلهای متعدد نگران نیستیم ‪ :‬ما صرفا ً بدون‬ ‫توضیح از يك فايل به فايل ديگر جست مي‌زند‪ ،‬به اين صورت رفتار‬

‫شبیه به رفتار ‪$‬‬

‫‪… p filenames‬‬ ‫‪$‬‬ ‫‪ t filenames … | p‬خواهد بود‪.‬‬

‫اگر نیاز به اسامي فايلها باشد‪ ،‬آنها مي‌توانند با يك حلقه ‪ For‬به صورت زير اضافه شوند ‪:‬‬

‫… ‪$ for i in filenames‬‬ ‫‪> do‬‬ ‫>‬ ‫‪echo $ i :‬‬ ‫>‬ ‫‪cat $ I‬‬ ‫‪> done | P‬‬

‫حقیقتاً ‪ ،‬ويژگیهای بسیار زيادی وجود دارند که ما مي‌توانیم به اين برنامه اضافه کنیم‪ .‬بهتر است که يك نسخه جدا شده بسازيم‪ ،‬سپس‬

‫بگذاريم گسترش يابد‪ ،‬به همان صورتي که تجربه پذيرفته میشود‪ .‬به اين صورت‪ ،‬ويژگیها از نوعي هستند که مردم حقیقتا ً طالب آنها‬

‫هستند و نه ويژگیهايي که ما فکر مي‌کنیم آنها مي‌خواهند‪.‬‬

‫ساختار اصلي ‪ ، P‬همانند ‪ vis‬مي‌باشد ‪ :‬زير برنامه اصلي ‪ ،‬درون فايلها تکرار مي‌شود و زير برنامه ‪ print‬را که بر روی هر کدام از آنها‬


‫محیط برنامه سازی لینوکس‬ ‫کار مي‌کند‪ ،‬فرا مي‌خواند‪.‬‬

‫‪196/322‬‬

‫‪/ * p : print input in chunks )version \( * /‬‬ ‫>‪# include < stdio . h‬‬ ‫‪# define PAGESIZE 22‬‬ ‫‪char‬‬ ‫‪* programe ; / * program name for error massage * /‬‬ ‫(‪main )argc , argv‬‬ ‫; ‪int argc‬‬ ‫; [ ] ‪char * argv‬‬ ‫}‬ ‫; ‪int i‬‬ ‫; ‪FILE * fp , * efopen < 1‬‬

‫; [‪Programe = argv ]0‬‬ ‫( ‪if ) argc = = 1‬‬ ‫; (‪print )stadin , PAGESIZE‬‬ ‫‪else‬‬ ‫} ( ‪for ) i = l ; i < argc ; i + +‬‬ ‫; (‪fp = < fopen )argv ]i [ , ″r″‬‬ ‫;(‪print )fp , PAGESIZE‬‬ ‫;(‪fclose )fp‬‬ ‫{‬ ‫;(‪exit )0‬‬ ‫{‬ ‫زير برنامه ‪ ، efopen‬يك عملکرد بسیار عمومي را وارد مي‌کند‪ .‬سعي کنید يك فايل را باز کنید؛ اگر امکان‌پذير نیست‪ ،‬يك پیغام خطا را‬

‫پرينت کنید و خارج شويد‪ .‬برای اينکه پیغامهای خطا را تشويق کنید که برنامه مزاحم (يا مزاحم شده) را شناسايي کنند‪ efopen ،‬به يك‬ ‫برنامه رشته خارجي استناد داده مي‌شود که شامل نام برنامه مي‌باشد و در ‪ main‬تنظیم مي‌شود‪.‬‬

‫‪/ * fopen file , die if )an.’t * /‬‬

‫(‪FILE * efopen )file , mode‬‬ ‫; ‪Char * file , * mode‬‬ ‫}‬ ‫; ( ) ‪FILE * fp , * fopen‬‬ ‫; ‪Extern char * programe‬‬

‫(‪if )) fp = fopen )file , mode(( ! = NULL‬‬ ‫; ‪return fp‬‬ ‫‪fprintf )stderr , ″ % s : can’t open file % s mode % s \ n ″ ,‬‬ ‫; ( ‪programe , file , mode‬‬ ‫; (‪exit )l‬‬

‫{‬

‫ما يك جفت از طرحهای ديگر را برای ‪ ،efopen‬قبل از فرو نشاندن بر روی اين برنامه‪ ،‬بررسي کرديم‪ .‬يکي از آنها ‪ ،‬قبل از چاپ کردن‬

‫پیام‪ ،‬با يك اشاره‌گر تهي که خرابي و اشکال را نشان مي‌دهد‪ ،‬آن را باز مي‌گرداند‪ .‬چنین چیزی به شماره گیرنده انتخاب ادامه يا خروج‬

‫را مي‌دهد‪ .‬طرحي ديگر‪ efopen ،‬را با سه‌آرگومان تهیه مي‌کند و اين آرگومانها مشخص مي‌کنند که آيا بايد پس از شکست در باز‬ ‫کردن فايل بازگشت يا خیر‪ .‬اما در اکثر مثالهای ما ‪ ،‬اشاره‌ای برای ادامه وجود ندارد‪ ،‬اگر نتوان به يك فايل دست يافت‪ ،‬بنابراين نسخه‌‬


‫محیط برنامه سازی لینوکس‬

‫‪197/322‬‬

‫فعلي از ‪ ، efopen‬بهترين نسخه برای استفاده مي‌باشد ‪.‬‬ ‫کار واقعي فرمان ‪ ، p‬در ‪ print‬انجام مي‌شود‪.‬‬

‫‪Print )fp , pagesize( / * print fp in pagesize chunks * /‬‬ ‫; ‪FILE * fp‬‬ ‫; ‪Int pagesize‬‬ ‫}‬ ‫‪static int lines = 0 ; / * number of lines sofar * /‬‬ ‫; [‪char buf ] BUFSIZ‬‬ ‫(‪while )fgets )buf , size of buf , fp( ! = NULL‬‬ ‫(‪if ) + + lines < page size‬‬ ‫; (‪fputs )buf , stdout‬‬ ‫} ‪else‬‬ ‫;‪buf ] strlen )buf( –1[ ′ \ 0 ′‬‬ ‫; (‪fputs )buf , stdout‬‬ ‫; (‪fflush )stdout‬‬ ‫; ( ) ‪ttyin‬‬ ‫; ‪lines = 0‬‬ ‫{‬

‫{‬

‫ما از ‪ BUFSIZ‬استفاده کرديم‪ ،‬که در > ‪ ، < stdio . h‬به عنوان اندازه میانگیر ورودی تعريف مي‌شود‪ ، buf , size , fp( fgets( .‬سطر‬

‫بعدی ورودی را از ‪ fp‬تا يك سطر جديد واکشي مي‌کند و سطر جديد را درون ‪ buf‬قرار مي‌دهد و يك \‪ 0‬پايان دهنده اضافه مي‌کند؛‬ ‫بیشتر ‪ ،‬کاراکترهای اندازه ‪ ، 1‬کپي مي‌شوند‪ BUFSIZ , NULL .‬را در انتهای فايل باز مي‌گرداند‪ fgets( .‬مي‌”وند بهتر طراحي شود ‪:‬‬

‫‪ fgets‬به جای يك تعداد کاراکتر‪ buf ،‬را باز مي‌گرداند؛ به علوه‪ ،‬هیچ اخطاری نمي‌دهد‪ ،‬اگر خط ورودی خیلي طولني باشد‪ .‬هیچ‬

‫کدام از کاراکترها مفقود نمي‌شوند‪ ،‬اما شما بايد برای مشاهده اينکه واقعا چه اتفاقي مي‌افتد به ‪ buf‬نگاه کنید‪).‬‬

‫تابع ‪ ،strlen‬طول يك رشته را باز مي‌گرداند؛ ما از آن برای اين منظور استفاده مي‌کنیم که سطر جديد پسین‪ ،‬آخرين سطر ورودی را‬

‫حذف کنیم‪ ، )F puts )buf , fp .‬رشته ‪ buf‬را روی فايل ‪ fp‬مي‌نويسد‪ .‬فراخواني ‪ ff lush‬در پايان صفحه‪ ،‬هر گونه خروجي میانگیر‬

‫شده را خارج مي‌کند‪.‬‬

‫وظیفه خواندن پاسخ از کاربر‪ ،‬پس اينکه هر صفحه پرينت شد‪ ،‬به يك زيربرنامه با عنوان ‪ ttyin‬فرستاده مي‌شود‪ Ttyin .‬نمي‌تواند‬

‫ورودی استاندارد را بخواند‪ ،‬چون ‪ p‬بايد کار کند حتي زماني که ورودی آن از يك فايل يا از يك لوله مي‌آيد‪ .‬برای بکارگیری آن‪،‬‬ ‫برنامه‪ ،‬فايل ‪ dev / tty /‬را باز مي‌کند‪ ،‬که پايانه کاربر‪ ،‬بدون توجه به هر گونه جهت‌دهي مجدد ورودی استاندارد‪ ،‬مي‌باشد‪.‬‬

‫ما ‪ ttyin‬را برای بازگرداندن اولین کاراکتر از پاسخ نوشتیم‪ ،‬اما از آن ويژگي در اينجا استفاده نمي‌شود‪.‬‬

‫‪)version 1( * /‬‬

‫‪ttyin ) ( / * process response from / dev / tty‬‬ ‫}‬ ‫; [‪char buf ] BUFSIZE‬‬ ‫; ( ) ‪FILE * efopen‬‬ ‫‪Static FILE * tty = NULL‬‬ ‫(‪if )tty = = NULL‬‬


‫محیط برنامه سازی لینوکس‬

‫‪198/322‬‬

‫;( ‪tty = efopen ) ″ / dev / tty ″ , ″r″‬‬ ‫( ‪if )fgets )buf , BUFIZE , tty( = = NULL | | buf ]0[ = = ′ q ′‬‬ ‫; (‪exit )0‬‬ ‫‪else‬‬ ‫‪/ * ordinary line * /‬‬ ‫; [‪return buf ]0‬‬

‫{‬

‫اشاره‌گر فايل ‪ ،devtty‬به صورت ‪ static‬اظهار مي‌شود‪ ،‬در نتیجه ارزش خود را از يك فراخوان از ‪ ttyin‬به فراخوان بعدی نگه مي‌دارد؛‬ ‫فايل ‪ ، dev / tty /‬فقط در اولین فراخوان باز مي‌شود‪.‬‬

‫به طور بديهي ويژگیهای ديگری وجود دارند که بايد بدون کار زياد ‪ ،‬به ‪ p‬اضافه شوند‪ ،‬اما ارزشي ندارد که نسخه اول ما از اين برنامه‪،‬‬

‫کاری را انجام دهد که در اينجا توصیف مي‌شود‪ 22 :‬سطر را پرينت کنید و منتظر بمانید‪ .‬قبل از اينکه ساير چیزها اضافه شوند‪ ،‬زمان‬

‫طولني بود و تا امروز فقط افراد کمي از اين ويژگي‌ها استفاده مي‌کنند‪.‬‬

‫يك ويژگي اضافي آسان ‪ ،‬تعیین تعداد سطرها در هر صفحه مي‌باشد‪ ،‬يك متغیر ‪ pagesize‬که مي‌تواند از سطر فرمان تنظیم شود ‪:‬‬

‫‪… p -n $‬‬ ‫قطعات را با ‪ n‬سطر‪ ،‬پرينت مي‌کند‪ .‬چنین چیزی فقط مستلزم اضافه کردن يك رمز آشنا در آغاز ‪ main‬مي‌باشد ‪:‬‬

‫‪/ * p : print input in chunks )rersion 2( * /‬‬ ‫…‬ ‫; ‪int i , pagesize = pAGESIZE‬‬ ‫; [‪programe = argv ]0‬‬ ‫} ( ‪if )argc > 1 $ $ argv ]1[ ]0[ = = ′ - ′‬‬ ‫;( [‪pagesize = atoi ) $ argv ]1[ ]1‬‬ ‫; ‪argc - -‬‬ ‫; ‪argv + +‬‬ ‫{‬ ‫…‬

‫تابع ‪ atoi‬يك رشته کاراکتر را به يك عدد صحیح تبديل مي‌کند (به (‪ atoi )3‬مراجعه کنید)‪.‬‬

‫افزايش ديگر به ‪ ، p‬توانايي گريز به طور موقت ‪ ،‬در پايان هر صفحه برای انجام فرماني ديگر مي‌باشد‪ .‬در مقايسه با ‪ ed‬و بسیاری ديگر‬ ‫از برنامه‌ها‪ ،‬اگر کاربر‪ ،‬سطری را تايپ کند که با يك علمت تعجب آغاز مي‌شود‪ ،‬مابقي سطر به عنوان يك فرمان تلقي مي‌شود و برای‬ ‫اجرا از شل عبور مي‌کند‪ .‬اين ويژگي نیز بي اهمیت است‪ ،‬چون تابعي با عنوان (‪ system )3‬وجود دارد که اين کار را انجام مي‌دهد‪ ،‬اما‬

‫توضیح زير را بخوانید‪ .‬نسخه اصلح شده ‪ ،ttyin‬به شرح زير است ‪:‬‬

‫‪ttyin ) ( / * process response from / dev / tty )version 2( * /‬‬ ‫}‬ ‫; [‪char buf ]BUFSIZ‬‬ ‫; ( ) ‪FILE * efopen‬‬ ‫; ‪Static FILE * tty = NNUL‬‬ ‫(‪if )tty = = NULL‬‬ ‫; ( ‪tty = efopen ) ″ / dev / tty ″ , ″ r ″‬‬


‫محیط برنامه سازی لینوکس‬

‫‪199/322‬‬

‫} ( ; ; ) ‪for‬‬ ‫‪if )fgets )buf , BUFSIZE , tty( = = NULL | | buf ]0[ = = ′q′‬‬ ‫; (‪exit )0‬‬ ‫} ( ‪else if )buf ]0[ = = ′ ! ′‬‬ ‫; (‪system )buf + 1‬‬ ‫‪/ * BUG here * /‬‬ ‫; (‪printf ) ″ ! \ n ″‬‬ ‫{‬ ‫‪else‬‬ ‫‪/ * ordinary line * /‬‬ ‫; [‪return buf ]0‬‬ ‫{‬

‫{‬

‫متأسفانه ‪ ،‬اين نسخه ازـ ‪ ttyin‬دارای يك خطای نامحسوس و خطرناك مي‌باشد‪ .‬فرمان‪ ،‬توسطـ ‪ system‬اجرا مي‌شوند و ورودی‬

‫استاندارد را از ‪ p‬مي‌گیرد ‪ ،‬بنابراين اگر ‌‪ ،p‬از لوله يا يك فايل خوانده شود‪ ،‬فرمان مي‌تواند با ورودی خودش‪ ،‬تداخل کند ‪:‬‬

‫‪ ed‬را از ‪ p‬مي‌گیرد‬

‫‪$ cat / etc / passwd | p – 1‬‬ ‫‪root : 3 D : f HR 5 KoB. 3 s : o : 1 : s . usr : / : ! ed‬‬

‫‪ etc / passwd … ed /‬را مي‌خواند‬

‫… غلط است و از سیستم خارج مي‌شود‬

‫؟‬ ‫!‬

‫راه حل ‪ ،‬مستلزم آگاهي در اين خصوص مي‌باشد که چگونه فرآيندهای يونیکس کنترل مي‌شوند و ما آن را در بخش ‪ 4‬ـ ‪ 7‬ارائه‬ ‫مي‌دهیم‪ .‬در حال حاضر‪ ،‬آگاه باشید که سیستم استادارد در کتابخانه مي‌تواند مشکل آفرين باشد‪ ،‬اما ‪ ttyin‬به درستي کار مي‌کند اگر با‬

‫نسخه ‪ system‬در فصل ‪ 7‬کامپايل شود‪.‬‬

‫ما اکنون دو برنامه نوشته‌ايم ‪ vis ،‬و ‪ p‬که بايد متغیرهای ‪ ،cat‬با اندکي شاخ و برگ تلقي شوند‪ .‬بنابراين ‪ ،‬آيا آنها بايد همگي بخشي از‬

‫‪ cat‬و قابل دستیابي توسط آرگومانهای اختیاری مانند – ‪ p‬و – ‪ v‬باشند؟ پرسش مربوط به اينکه آيا يك برنامه جديد بنويسیم يا‬

‫ويژگیها را به برنامه قبلي اضافه کنیم‪ ،‬مکررا ً مطرح مي‌شود‪ ،‬مادامي که افراد عقايد جديد دارند‪ .‬ما يك پاسخ قطعي نداريم‪ ،‬اما اصولي‬ ‫وجود دارند که به تصمیم‌گیری در اين زمینه کمك مي‌کنند‪.‬‬

‫اصل مهم‪ ،‬اين است که برنامه بايد فقط يك کار اصلي را انجام دهد ـ اگر کارهای زيادی را انجام دهد‪ ،‬بزرگتر‪ ،‬کندتر و سختتر قابل‬

‫نگهداری و سخت‌تر قابل استفاده مي‌باشد‪ .‬به راستي ‪ ،‬ويژگیها‪ ،‬اغلب بدون استفاده مي‌مانند‪ ،‬چون مردم نمي‌توانند انتخابها را به خاطر‬

‫بسپارند‪.‬‬

‫اين موضوع بیان مي‌کند که ‪ cat‬و ‪ vis‬نبايد ترکیب شوند‪ Cat .‬فقط ورودی خودش را کپي مي‌کند ‪ ،‬بدون اينکه آن را تغییر دهد‪ ،‬در‬

‫حالیکه ‪ vis‬آن را منتقل مي‌کند‪ .‬ترکیب آنها‪ ،‬برنامه‌ای مي‌سازد که دو چیز متفاوت را انجام مي‌دهند‪ .‬اين حالت تقريبا ً با ‪ cat‬و ‪ p‬نیز‬ ‫آشکار مي‌باشد‪ Cat .‬برای کپي کردن سريع وموثر معني مي‌دهد‪ ،‬در حالیکه ‪ p‬برای گرفتن اطلعات معني مي‌دهد‪ .‬و ‪ p‬ورودی خودش‬

‫را منتقل مي‌کند ‪ :‬هر سطر جديد بیست و دوم‪ ،‬حذف مي‌شود‪ .‬سه برنامه مجزا به نظر طرح صحیحي مي‌آيند‪.‬‬

‫تمرين ‪ 6‬ـ ‪ 6‬ـ آيا ‪ p‬به طور معقول عمل مي‌کند اگر ‪ pagesize‬مثبت نباشد؟‬


‫محیط برنامه سازی لینوکس‬

‫‪200/322‬‬

‫تمرين ‪ 7‬ـ ‪ 6‬ـ چه چیز ديگری مي‌توان با ‪ p‬انجام داد؟ توانايي برای پرينت مجدد بخش‌های ورودی قبلي را (اگر مناسب است) ارزيابي‬ ‫و اجرا کنید‪( .‬اين يك ويژگي اضافي است که ما از آن استفاده مي‌کنیم)‪ .‬يك مسیر ساده را برای مجاز کردن پرينت کمتر از يك پرده پر‬

‫از ورودی پس از هر وقفه‪ ،‬اضافه کنید‪ .‬يك مسیر ساده را برای پويش به طرف جلو يا به طرف عقب برای يك سطر مشخص شده‬

‫توسط عدد يا محتوا ‪ ،‬اضافه کنید‪.‬‬

‫تمرين ‪ 8‬ـ ‪ 6‬ـ از توانايي‌های کار ـ گرداني فايل ‪ exes‬توکار شل استفاده کنید (برای تثبیت فراخوان ‪ ttyin‬با سیستم به ‪ )sh )1‬مراجعه‬ ‫کنید)‪.‬‬

‫تمرين ‪ 9‬ـ ‪ 6‬ـ اگر شما فراموش کنید که يك ورودی را برای ‪ p‬مشخص کنید ‪ p ،‬به آرامي منتظر ورودی از پايانه باقي مي‌ماند‪ .‬آيا‬ ‫کشف اين خطای احتمالي‪ ،‬ارزشمند است؟ اگر ارزشمند است؟ چگونه ؟ توجه ‪)isutty )3 :‬‬

‫‪ 5‬ت‪ 6 ‬ت‪ ‬يك‪ ‬مثال‪pick : ‬‬ ‫نسخه ‪ Pick‬در فصل ‪ ،5‬به وضوح توانايي‌های شل را گسترش مي‌دهد‪ .‬نسخه ‪ c‬که اکنون بیان مي‌شود‪ ،‬تا حدودی متفاوت از نسخه ‪c‬‬

‫موجود در فصل ‪ 5‬مي‌باشد‪ .‬اگر اين نسخه دارای آرگومانها باشد‪ ،‬آنهاهمانند قبل پردازش مي‌شوند‪ .‬اما اگر تنها آرگومان ’ـــ ‘ مشخص‬

‫شود‪ ، Pick .‬ورودی استاندارد آن را پردازش مي‌کند‪.‬‬

‫اگر هیچ آرگوماني وجود نداشته باشد‪ ،‬چرا ورودی استاندارد خوانده نمي‌شود؟ نسخه دوم فرمان ‪ zap‬را در بخش ‪ 6‬ـ ‪ 5‬در نظر بگیريد‬

‫‪:‬‬

‫‪kill $ SIG ′ pick [ ′ ps – ag | egrep ″ $ * ″ ′ \ | awk ′ }print $ 1 {′‬‬ ‫چه اتفاقي مي‌افتد اگر طرحـ ‪ egrep‬چیزی را تطبیق نکند؟ در اين حالت‪،‬ـ ‪ pick‬هیچ آرگوماني ندارد و شروع به خواندن ورودی‬

‫‪ ، zap‬در يك روش گیج کننده‪ ،‬خراب مي‌شود‪ .‬نیاز به يك آ‌رگومان آشکار‪ ،‬يك روش آسان برای غیر‬ ‫‌‬ ‫استاندارد خود مي‌کند؛ فرمان‬ ‫مبهم کردن چنین موقعیتهايي مي‌باشد و قرارداد ’ـــ ‘ از ‪ cat‬و ساير برنامه‌ها‪ ،‬نشان مي‌دهد که چگونه آن را تشخیص دهیم‪.‬‬

‫‪/ * pick : offer choice on each argument * /‬‬ ‫> ‪# include < stdio. h‬‬ ‫‪char‬‬ ‫‪* programe ; / * program name for error message * /‬‬

‫(‪main )argc , argv‬‬ ‫; ‪int argc‬‬ ‫; [ ] ‪char * argv‬‬ ‫}‬ ‫; ‪int i‬‬ ‫; [‪char buf ] BUFSIZ‬‬ ‫; [‪programe = argv ]0‬‬ ‫‪if )argc = = 2 $ $ strcmp )argv ]1[ , ″__″ ( = = o ( / * pick _ * /‬‬ ‫} (‪while )fgets )buf , sizeof buf , stdin( i = NULL‬‬


‫محیط برنامه سازی لینوکس‬

‫‪201/322‬‬

‫‪buf ] strlen )buf( –1 [ = ′ \ o ′ ; / * drop newline * /‬‬ ‫; ( ‪pick )buf‬‬

‫{‬

‫( ‪for ) i = l ; i < argc ; i + +‬‬ ‫; ( [‪pick )argv ]i‬‬ ‫; ( ‪exit ) 0‬‬

‫‪else‬‬

‫{‬ ‫‪pick )s( / * offer choice of s * /‬‬ ‫; ‪char * s‬‬ ‫}‬ ‫; ( ‪fprintf )stderr , ″ % s? ″ , s‬‬ ‫(‪if )ttyin ) ( = = ′ y ′‬‬ ‫; ( ‪print f ) ″ % s \ n ″ , s‬‬ ‫{‬ ‫‪ pick‬برای انتخاب آرگومانها به طور برهم‌کنشي يك مسیر ساده را در يك برنامه متمرکز مي‌کند‪ .‬چنین چیزی نه تنها يك کار مفید را‬ ‫فراهم مي‌کند‪ ،‬بلکه همچنین نیاز به انتخابهای برهم‌کنشي را بر روی ساير فرمانها کاهش مي‌دهد‪.‬‬

‫تمرين ‪ 10‬ـ ‪ 6‬ـ با توجه به ‪ ، pick‬آيا نیاز به ‪ rm – i‬وجود دارد ؟‬

‫‪ 6‬ت‪ 6 ‬ت‪ ‬روي‪ ‬خطاها‪ ‬و‪ ‬خطازدايي‪ ‬‬ ‫ل يك برنامه نوشته باشید‪ ،‬با تصور يك خطا آشنا هستید‪ .‬راه حل خوبي برای نوشتن رمز بدون خطا وجود ندارد به جز اينکه‬ ‫اگر شما قب ً‬ ‫مراقب باشیم که يك طرح ساده و تمیز به وجود ‌آوريد و آن را به دقت اجرا کنید و آن را تمیز نگه داريد‪ ،‬همچنانکه آن را تغییر‬ ‫مي‌دهید‪.‬‬

‫ابزار اندکي از يونیکس وجود دارند که به شما در پیدا کردن خطاها کمك مي‌کنند‪ ،‬اگر چه هیچ کدام از آنها واقعا ً عالي نمي‌باشند ‪ .‬اما‬

‫برای شرح آنها‪ ،‬ما به يك خطا نیاز داريم و همه برنامه‌های موجود در اين کتاب کامل هستند‪ .‬بنابراين‪ ،‬ما يك خطای نمونه ايجاد‬

‫مي‌کنیم‪.‬‬

‫تابع ارائه شده ‪ pick‬در بال‪ ،‬را در نظر بگیريد‪ .‬در اين جا نیز وجود دارد‪ ،‬اما اکنون دارای يك خطا مي‌باشد‪( .‬نیازی نیست که دوباره آن‬ ‫را از اول تکرار کنیم)‪.‬‬

‫‪pick ) s( / * offer choice of s * /‬‬ ‫; ‪Char * s‬‬ ‫}‬ ‫; ( ‪fprint ) ″ % s ? ″ , s‬‬ ‫( ‪if )ttyin ) ( = = ′ y ′‬‬ ‫; ( ‪print f ) ″ % s \ n ″ , s‬‬ ‫{‬


‫محیط برنامه سازی لینوکس‬

‫‪202/322‬‬

‫اگر ما آن را کامپايل و سپس اجرا کنیم ‪ ،‬چه اتفاقي مي‌افتد؟‬

‫‪pick . c – o pick ( ( $‬‬ ‫‪pick * . c $‬‬

‫‪)memory fault )ore dumped‬‬

‫آن را بررسي کنید‬

‫ناپديد مي‌شود !‬

‫“‪ ” memory fault‬به اين معناست که برنامه شما سعي مي‌کند به بخشي از حافظه مراجعه کند‬

‫که مجاز نمي‌باشد‪ .‬معمول ً به اين معناست که يك اشاره‌گر‪ ،‬به جايي نامعقول اشاره مي‌کند‪ ، ”Bus error“ .‬تشخیصي ديگر با همین‬

‫معني مي‌باشد و اغلب با پويش کردن يك رشته پايان نیافته‪ ،‬بوجود مي‌آيد‪.‬‬

‫“ ‪ ، ” cor dumped‬به اين معناست که کرنل ‪ ،‬وضعیت برنامه اجرا کنندة شما را در يك فايل با نام ‪ core‬در فهرست ذخیره مي‌کند‪.‬‬

‫شما همچنین مي‌توانید يك برنامه را مجبور کنید که با تايپ ‪ ، \ctl – 1‬حافظه اصلي را خالي کند‪ ،‬البته اگر در پیش زمینه اجرا مي‌شود‬ ‫و يا با نرمال ‪ ، kill-3‬حافظه اصلي را خالي کنید‪ ،‬البته اگر در پیش زمینه مي‌باشد‪.‬‬

‫دو برنامه برای نوشتن در حافظه وجود دارد‪ adb ،‬و ‪ .sdb‬همانند اکثر خطا زداها ‪ ،‬آنها مرموز ‪ ،‬پیچیده و ضروری هستند‪ Adb .‬در‬

‫هفتمین ويرايش وجود دارد؛ ‪ sdb‬در اکثر نسخه‌های اخیر سیستم در دسترس مي‌باشد‪ .‬يکي از اين دو برنامه‪ ،‬مطمئنا ً در سیستم وجود‬ ‫دارند‪.‬‬

‫ما در اينجا فقط به حداقل استفاده قطعي از هر کدام از آنها مي‌پردازيم ‪ :‬پرينت کردن يك‬

‫‪ ، stack trace‬که تابعي است که زماني اجرا شد که برنامه به پايان رسید‪ ،‬تابعي که آن را فراخواند و مواردی از اين قبیل ‪ .‬اولین تابع‬

‫نامگذاری شده در ‪ ،stack trace‬در جايي است که برنامه وجود داشت زماني که خاموش شد‪.‬‬ ‫برای اجرای يك ‪ stack trace‬با ‪ ، adb‬فرمان ‪ c $ ،‬مي‌باشد ‪:‬‬

‫به ‪ adb‬استناد مي‌کند‬

‫‪adb pick core $‬‬

‫‪ stack trace‬را درخواست مي‌کند‬

‫‪c $‬‬

‫) ‪- strout‬و ‪ 0‬و ‪ 011‬و ‪)011200 01155772‬‬ ‫‪°‬‬ ‫‪adjust :‬‬ ‫‪fillch :‬‬ ‫‪060542‬‬ ‫( و ‪ 0‬و ‪ 011‬و ‪doprnt ) 011200 01155722‬‬ ‫(و ‪f print f )0177345 011200‬‬

‫‪011200‬‬ ‫‪0177345‬‬ ‫‪°‬‬

‫‪0177345‬‬

‫‪0177234‬‬ ‫از سیستم خارج شويد‬

‫‪035‬‬ ‫‪01‬‬ ‫‪°‬‬

‫‪iop :‬‬ ‫‪fmt :‬‬ ‫‪args :‬‬ ‫(‪pick )0177345‬‬ ‫‪s:‬‬ ‫(و ‪main )0177234 035‬‬ ‫‪argc :‬‬ ‫‪argv :‬‬ ‫‪i:‬‬ ‫‪buf :‬‬

‫‪ctl – d‬‬


‫محیط برنامه سازی لینوکس‬

‫‪203/322‬‬

‫‪$‬‬ ‫اين برنامه ‪ ،‬بیان مي‌کند کهـ ‪ main ، pick‬را فراخواند‪ ،‬که در نتیجه ـ ‪ fprintf‬را فراخواند‪،‬ـ ‪ fprintf ، doprnt‬ـ را فراخواند و –‬ ‫‪ doprint ، - strout‬را فراخواند‪ .‬چون – ‪ dopmt‬در هیچ جايي در ‪ pick.c‬ذکر نمي‌شود‪ ،‬در نتیجه مشکلت ما بايد جايي در ‪fprintf‬‬

‫يا بالتر باشند‪( .‬سطرها پس از هر زيربرنامه درـ ‪ ، traceback‬ارزش متغیرهای محلي را نشان مي‌دهند‪ c$ .‬اين اطلعات را حذف‬ ‫مي‌کند‪ ،‬همان کاری که ‪ c$‬خودش در برخي از نسخه‌های ‪ adb‬انجام مي‌دهد)‬

‫قبل‬

‫همه اين موارد ‪ ،‬همین مورد را با ‪ sdb‬بررسي مي‌کنیم ‪:‬‬

‫‪$ sdb pick core‬‬ ‫‪warning : ′ a . out ′ not compiled with – g‬‬ ‫‪.‬زير برنامه در جايي که برنامه به پايان مي‌رسد ‪iseek : address oxa 64‬‬

‫‪stack trace‬را درخواست مي‌کند‬

‫‪* t‬‬ ‫( ) ‪isseek‬‬ ‫(‪fprintf )54 91 47 47 21 540 61‬‬ ‫( ‪pick ) 54 91 47 47 21‬‬ ‫( و ‪ 21 47 47 89 88‬و ‪main ) 12 91 47 47 21 30‬‬ ‫از سیستم خارج شويد‬

‫‪*q‬‬

‫اطلعات به صورت متفاوت فرمت مي‌شوند‪ ،‬اما يك موضوع عمومي وجود دارد‪:‬‬

‫‪$‬‬

‫‪ fprintf . ) traceback‬متفاوت است چون بر روی يك ماشین متفاوت اجرا شد ــ ‪ 11/750‬ــ ‪ VAX‬ـ که دارای يك پیاده‌سازی‬ ‫متفاوت از کتابخانه استاندارد ‪ I / O‬مي‌باشد)‪ .‬و مطمئناً‪ ،‬اگر ما در نسخه خراب ‪ pick‬به درخواست ‪ fprintf‬نگاه کنیم‪ ،‬اشتباه است ‪:‬‬

‫; ( ‪f print f ) ″ % s ″ , s‬‬ ‫‪ stderr‬وجودت تندارد‪،‬ت تبنابراينت ترشتهت تفرمتت ‪، % s?″‬ت تبهت تعنوانت تيكت تاشاره‌گرت ‪ FILE‬استفاده‬ ‫مي‌شود و البته بي‌نظمي رخ مي‌دهد‪.‬‬ ‫ما اين خطا را پاك کرديم‪ ،‬چون عمومي است‪ ،‬يك نتیجه از بي‌توجهي به جای طرح بد‪ .‬همچنین اين امکان وجود دارد که خطاها را به‬

‫اين صورت پیدا کنیم‪ ،‬که در آن يك تابع با آرگومانهای اشتباه و از طريق استفاده از ‪ ، )lint )1‬درستي سنجي ‪ ، c‬فراخوان مي‌شود‪.‬‬

‫‪ Lint‬به بررسي برنامه‌های ‪ c‬به منظور يافتن خطاهای بالقوه‪ ،‬مشکلت قابل حمل و ساختاهاری مشکوك مي‌پردازد‪ .‬اگر ما ‪ lint‬را روی‬ ‫کل فايل ‪ pick.c‬اجرا کنیم‪ ،‬خطا مشخص مي‌شود ‪:‬‬

‫‪$ lint pick . c‬‬ ‫……‬ ‫(‪fprintf , arg . l used in consistently ″ llib – 1 c″ )69( : : ″ pick.c ″ )28‬‬

‫در ترجمه ‪ ،‬اين برنامه بیان مي‌کند که اولین آرگومان ‪ fprintf‬در تعريف کتابخانه استاندارد‪ ،‬از استفاده آن د ر ‪ 28‬سطر از برنامه‌ها‪،‬‬

‫متفاوت مي‌باشد‪ .‬اين يك تذکر قوی درباره چیزی مي باشد که اشتباه است‪.‬‬

‫‪ ، Lint‬يك موفقیت مرکب است‪ Lint .‬دقیقا ً بیان مي‌کند که چه چیزی در اين برنامه اشتباه است‪ ،‬اما همچنین تعداد زيادی از پیامهای‬

‫نامربوط را تولید مي‌کند که ما در بال حذف کرديم و مستلزم مقداری تجربه در اين خصوص مي‌باشد که بدانیم به چه چیزی توجه شود‬

‫و چه چیزی ناديده گرفته شود‪ .‬اگر چه تلش ارزشمندی است ‪ ،‬چون ‪ lint‬برخي از خطاهايي را پیدا مي‌کند که تقريباً غیرممکن است‬


‫محیط برنامه سازی لینوکس‬

‫‪204/322‬‬

‫افراد آنها را ببینند‪ .‬اجرای ‪ lint‬پس از يك زماني طولني از ويرايش ‪ ،‬ارزشمند است و اطمینان مي‌دهد که شما هر اخطاری را که‬ ‫مي‌دهد ‪ ،‬درك مي‌کنید‪.‬‬

‫‪ 7‬ت‪ 6 ‬ت‪ ‬يك‪ ‬مثال‪zap : ‬‬ ‫‪ ، zap‬که به صورت انتخابي‪ ،‬فرآيندها را حذف مي‌کند‪ ،‬برنامه ديگری است که ما آن را به عنوان يك فايل شل در فصل ‪ ، 5‬ارائه‬ ‫داديم‪ .‬مشکل عمده با اين نسخه‪،‬سرعت است ‪ zap :‬فرآيندهای زيادی را بوجود مي‌آورد که به کندی آنها را اجرا مي‌کند؛ و بويژه برای‬

‫برنامه‌ای که فرآيندهای خاطي را حذف مي‌کند‪ .‬نوشتن مجدد ‪ zap‬در ‪ ، c‬آن را سريعتر مي‌کن‪ .‬اما ما قصد نداريم که کل کار را در اينجا‬

‫انجام هیم ‪ :‬ما هنوز از ‪ ps‬برای پیدا کردن اطلعات فرآيند استفاده مي‌کنیم‪ Ps .‬خیلي آسانتر از خارج کردن اطلعات از کرنل مي‌باشد و‬

‫قابل انتقال نیز مي‌باشد‪ ، zap .‬يك لوله را با ‪ ps‬بر روی انتهای ورودی باز مي‌کند و از روی آن مي‌خواند به جای اينکه از يك فايل‬

‫بخواند‪ .‬تابع (‪ ،popen )3‬مشابه به ‪ fopen‬مي باشد‪ .‬به جز اينکه اولین ‌آرگومان ‪ ،‬يك فرمان است به جای اينکه يك اسم فايل باشد‪.‬‬ ‫همچنین يك ‪ pclose‬وجود دارد که ما در اينجا به آن نیازی نداريم‪.‬‬

‫‪/ * zap : interactive process killer * /‬‬ ‫> ‪# include < stadio . h‬‬ ‫> ‪# include <signal. h‬‬ ‫; ‪char * programe‬‬ ‫‪/ * program name for error message * /‬‬ ‫‪char‬‬ ‫‪* ps = ″ ps – ag ″ ; / * system dependent * /‬‬ ‫( ‪main ) argc , argv‬‬ ‫; ‪int argc‬‬ ‫; [ ] ‪char * argv‬‬ ‫}‬ ‫; ( ) ‪FILE * fin , * popen‬‬ ‫; [‪Char buf ] BUFSIZ‬‬ ‫; ‪int pid‬‬

‫; [‪progname – argv ]0‬‬ ‫} (‪if )) fin = popen )ps , ″ r ″ (( = = NULL‬‬ ‫; (‪fprint f )stderr , ″ % s : can’t run % s \ n ″ , progname , ps‬‬ ‫; (‪exit )1‬‬ ‫{‬ ‫; (‪fgets )buf , size of buf , fin‬‬ ‫‪/ * get header line * /‬‬ ‫; ( ‪fprintf )stderr , ″ % s ″ , buf‬‬ ‫( ‪while )fgets )buf , size of buf , fin( ! = NULL‬‬ ‫} ( ‪if )argc = = l | | strindex )buf , argv ]1[ (> = 0‬‬ ‫‪buf ] strlen )buf ( – 1[ = ′ \ 0 ′; / * suppress \ n * /‬‬ ‫; (‪fprintf )stderr , ″ % sp ″ , buf‬‬ ‫} ( ‪if )ttyin ) ( = ′ y ′‬‬ ‫;‪sscanf )buf , ″ % d ″ , $ pid0‬‬ ‫; (‪kill )pid , SIGKLL‬‬ ‫{‬ ‫{‬


‫محیط برنامه سازی لینوکس‬

‫‪205/322‬‬

‫; (‪exit ) 0‬‬

‫{‬

‫ما برنامه را برای استفاده از ‪ ps – ag‬نوشتیم (انتخاب وابسته به سیستم مي‌باشد)‪ ،‬اما شما مي‌توانید فقط فرآيندهای خود را حذف کنید‬ ‫مگر اينکه شما ابرکاربر باشید‪ .‬اولین فراخوان برای ‪ ، fgets‬سطر عنوان را از ‪ ، ps‬پاك مي‌کند؛ اين يك عملکرد جالب برای استنتاج‬

‫چیزی است که اتفاق مي‌افتد‪ ،‬اگر شما سعي کنید فرآيندی را که مطابق با آن سطر عنوان مي‌باشد‪ ،‬حذف کنید ‪.‬‬

‫تابع ‪ ، sscanf‬عضوی از خانواده ‪ )scanf )3‬برای انجام تبديل فرمت ورودی مي‌باشد‪ .‬اين تابع‪ ،‬از يك رشته تبديل مي‌شود به جای‬ ‫اينکه از يك فايل تبديل شود‪.‬‬

‫فراخوان ‪ kill‬از سیستم‪ ،‬علمت خاصي را به فرآيند مي‌فرستد ؛ علمت ‪ SI GKI LL‬که در‬

‫> ‪ < signal. h‬تعريف مي‌شود و نمي‌تواند متوقف شود و يا ناديده گرفته شود‪ .‬شما ممکن است از فصل ‪ 5‬به خاطر آوريد که ارزش‬

‫عددی آن ‪ 9‬است‪ .‬اما عملکرد بهتر‪ ،‬استفاده از ثابت‌های نمادی از فايلهای عنوان مي‌باشد‪ ،‬به جای اينکه برنامه‌های خود را با اعداد‬ ‫جادويي ‪ ،‬بیان کنید‪.‬‬

‫اگر هيچ آرگوماني وجود نداشته باشد‪ zap ،‬هر سطر از ورودي ‪ Ps‬را براي انتخاب ممكن‪،‬‬ ‫ارائهت تمي‌دهد‪ .‬اگرت تيكت تآرگومانت توجودت تداشتهت تباشد‪ .‬درت تنتيجهت ‪، zap‬ت تفقطت تسطرهايي تاز‬ ‫خروجي ‪ ps‬را ارائه مي‌دهد كه آن را تطبيق كنند‪ .‬تابع (‪ ،s1 , s2( strindex‬بررسي مي‌كند كه‬ ‫آيا آرگومان‪ ،‬بخشي از تيك سطر از خروجيت ‪ ps‬رات تطبيق مي‌كند يا نه و تاين كار را با‬ ‫استفاده از ‪ st rn cmp‬انجام مي‌دهد (جدول ‪ 2‬ت ‪.)6‬‬ ‫‪ ،Strindex‬موقعيت در ‪ s1‬را به جايي باز مي‌گرداند كه ‪ s2‬رخ مي‌دهد و يا به –‪ 1‬باز مي‌گرداند‪،‬‬ ‫اگر ‪ s2‬وجود نداشته باشد‪.‬‬ ‫‪strindex )s , t ( / * return index of tins , - 1 if none * /‬‬ ‫; ‪char * s , * t‬‬ ‫}‬ ‫; ‪int i , n‬‬ ‫; (‪n = strlen )t‬‬ ‫( ‪for ) i = o ; s ]i[ ! = ′ \ o ′ ; i + +‬‬ ‫( ‪for )strncmp )sti , t , n ( = = 0‬‬ ‫; ‪return i‬‬ ‫; ‪return – 1‬‬ ‫{‬ ‫جدول ‪ 4‬ـ ‪ 6‬ـ تابعهايي را که عموماً استفاده مي‌شوند‪ ،‬از کتابخانه استاندارد ‪ I / O‬را به طور خلصه بیان مي‌کند‪.‬‬

‫تمرين ‪ 11‬ـ ‪ 6‬ـ ‪ zap‬را به گونه‌ای تغییر دهید که هر تعداد از آرگومانها بتوانند ذخیره شوند‪ .‬همانگونه که نوشته شد‪ zap ،‬در حالت‬

‫عادی‪ ،‬سطر را بر طبق خودش به عنوان يکي از انتخابها ‪ ،‬پژواك مي‌کند‪‌ .‬آيا بايد اينگونه باشد؟ اگر نه‪ ،‬برنامه را متعاقباً تغییر دهید ‪ :‬نکته‬

‫‪.)get pid )3 :‬‬


‫محیط برنامه سازی لینوکس‬

‫‪206/322‬‬

‫تمرين ‪ 12‬ـ ‪ 6‬ـ يك تابع ‪ )fgrep )1‬در اطراف ‪ strindex‬بسازيد‪ .‬زمانهای اجرا برای جستجوهای پیچیده را با هم مقايسه کنید‪ ،‬ده‬ ‫کلمه را در يك سند بیان کنید‪ .‬چرا ‪ fgrep‬سريعتر عمل مي‌کدن؟‬

‫‪ 8‬ت‪ 6 ‬ت‪ ‬يك‪ ‬برنامه‪ ‬مقايسه‪ ‬فايل‪ ‬برهم‪ ‬كنش‪idiff : ‬‬ ‫يك مشکل عمومي ‪ ،‬داشتن دو نسخه از يك فايل مي‌باشد‪ ،‬که تا حدودی متفاوت هستند و هر کدام شامل بخشي از يك فايل مطلوب‬

‫مي‌باشند؛ چنین چیزی اغلب زماني بوجود مي‌آيد که تغییرات به طور مستقل توسط دو فرد متفاوت انجام شوند‪ Diff .‬به شما مي‌گويد‬

‫که چگونه فايلها با هم تفاوت دارند‪ ،‬اما ‪ diff‬به طور مستقیم به شما کمك نمي‌کند‪،‬اگر شما بخواهید بخشي از قسمتهای اولین فايل و‬ ‫برخي از قسمتهای دومین فايل را انتخاب کنید‪.‬‬

‫در اين بخش ‪ ،‬ما يك برنامه ‪ idiff )diff‬برهم کنشي) مي‌نويسیم که هر قطعه از خروجي ‪ diff‬را ارائه مي‌دهد و اختیار انتخاب بخش «‬

‫‪ »from‬انتخاب بخش «‪ »to‬يا ويرايش بخش را پیشنهاد مي‌کند‪.‬‬

‫‪ ، idiff‬قطعات انتخاب شده را در يك ترتیب صحیح‪ .‬در يك فايل با عنوان ‪ idiff . out‬قرار مي‌دهد‪ .‬که با توجه به اين دو فايل‬

‫مي‌باشد ‪:‬‬

‫‪file 1 :‬‬ ‫‪this is‬‬ ‫‪a tegt‬‬ ‫‪of‬‬ ‫‪your‬‬ ‫‪skill‬‬ ‫‪and comprehension‬‬ ‫‪diff produces‬‬

‫‪file 2:‬‬ ‫‪this is‬‬ ‫‪hot a test‬‬ ‫‪of‬‬ ‫‪our‬‬ ‫‪ability‬‬

‫جدول‪ 4  ‬ت‪ 6  ‬ت‪ ‬تابعهاي‪ ‬مفيد‪ ‬و‪ ‬استاندارد‪I / O  ‬‬

‫فايل < را باز مي‌كند؛ وضعيت ‪ r″ ، w″ ، a″‬براي‬

‫‪)fp = fopen ) s , mode‬‬

‫خواندن‪ ،‬نوشتن ‪ ،‬ضمیمه کردن ‪ )NULL‬را برای خطا باز مي‌گرداند)‬

‫کاراکتر را مي‌گیرد؛ ‪ ) ( getc ) st din( , get char‬مي‌باشد‬

‫‪)c = gctc )ff‬‬

‫کاراکتر را قرار مي‌دهد؛ ‪ )putc ) c , std out( , put char ) c‬مي‌باشد‬ ‫کاراکتر را بر روی فايل ورودی ‪ fp‬قرار مي دهد؛ حداکثر يك ‪char‬‬

‫‪)putc )c , fp‬‬ ‫‪)ungetc )c , fp‬‬

‫مي‌تواند در يك زمان به عقب برگردد‪.‬‬

‫کاراکترها (از ‪ ، a) , … , ( stdin‬بر طبق ‪fmt‬‬

‫‪scanf )fmt , al‬‬

‫مي‌خواند‪ .‬هر ‪ ai‬بايد يك اشاره‌گر باشد‪.‬‬

‫‪ EOF‬های بازگشت يا تعداد میدانها معکوس مي‌شوند‪.‬‬

‫از فايل ‪ fp‬مي‌خواند‬ ‫از فايل ‪ s‬مي‌خواند‬

‫‪)… , f scanf )fp‬‬ ‫‪)… , ss can f )s‬‬

‫‪)… ,‬‬


‫محیط برنامه سازی لینوکس‬

‫‪207/322‬‬

‫‪ … , al‬را بر طبق ‪ fmt‬فرمت مي‌کند و بر روی ‪ stout‬پرينت مي‌کند‬

‫‪)… , print f )fmt , al‬‬

‫… را بر روی فايل ‪ fp‬پرينت مي‌کند‬

‫‪)… , fprint f )fp‬‬

‫… را درون رشته ‪ ،s‬پرينت مي‌کند‬

‫‪)… , sprintf )s‬‬

‫حداکثر ‪ n‬کاراکتر را از ‪ ، fp‬درون ‪ s‬مي‌خواند‬

‫‪)fget s )s , n , fp‬‬

‫‪ NULL‬را در انتهای فايل باز مي‌گرداند‪.‬‬

‫رشته ‪ s‬را بر روی فايل ‪ fp‬پرينت مي‌کند‬

‫‪)f puts )s , fp‬‬

‫هر گونه خروجي میانگیر شده‪ ،‬بر روی فايل ‪ fp‬را پاك مي‌کند‬

‫فايل ‪ fp‬را مي‌بندد‬

‫‪)f flush )fp‬‬ ‫‪)f close )fp‬‬

‫لوله را برای فرمان ‪ s‬باز مي‌کند‪ Fopen .‬را مشاهده کنید‬ ‫لوله ‪ fp‬را مي‌بندد‬

‫‪)fp = popen )s , mode‬‬ ‫‪)pclose )fp‬‬

‫فرمان ‪ s‬را اجرا مي‌کند و منتظر کامل شدن آن باقي مي‌ماند‬

‫‪)system )s‬‬

‫‪$ diff file 1 file 2‬‬ ‫‪2c2‬‬ ‫‪< a test‬‬ ‫……‬ ‫‪> not a test‬‬ ‫‪4,6c4,5‬‬ ‫‪< your‬‬ ‫‪< skill‬‬ ‫‪< and comprehension‬‬ ‫……‬ ‫‪> our‬‬ ‫‪> ability‬‬ ‫‪$‬‬ ‫‪ :‬مانند زير مي‌باشد ‪ idiff‬يك مکالمه با‬ ‫اولین تفاوت‬

‫را انتخاب مي‌کند ( < ) کاربر نسخه دوم‬ ‫دومین تفاوت‬

‫‪$ idiff file 1 file 2‬‬ ‫‪2c2‬‬ ‫‪< a test‬‬ ‫………‬ ‫‪> not a test‬‬ ‫> ?‬ ‫‪4,6c4 ,5‬‬ ‫‪< your‬‬ ‫‪< skill‬‬ ‫‪< and comprehension‬‬ ‫……‬ ‫‪> our‬‬


‫محیط برنامه سازی لینوکس‬

‫‪208/322‬‬

‫را انتخاب مي‌کند (>) کاربر اولین نسخه‬ ‫خروجي در اين فايل قرار مي‌گیرد‬

‫‪> ability‬‬ ‫<?‬ ‫‪idiff out put in file idiff . out‬‬ ‫‪$ cat idiff . out‬‬ ‫‪this is‬‬ ‫‪not a test‬‬ ‫‪of‬‬ ‫‪your‬‬ ‫‪skill‬‬ ‫‪and comprehesion‬‬ ‫‪$‬‬

‫اگر بجای < يا > پاسخ ‪ e‬داده شود‪ ،‬در نتیجه ‪ idiff ، ed ،‬را به دو گروه از سطرهايي که خوانده مي‌شوند‪ ،‬استناد مي‌کند‪ .‬اگر دومین‬ ‫پاسخ ‪ e‬بوده باشد‪ ،‬در نتیجه‪ ،‬میانگیر ويراستار به اين صورت به نظر مي‌رسد ‪:‬‬

‫هر چیزی که درون فايل توسط ‪ ed‬نوشته مي‌شود‪ ،‬چیزی است که وارد خروجي نهايي مي‌شود‪.‬‬

‫‪your‬‬ ‫‪skill‬‬ ‫‪and comprehesion‬‬ ‫……‬ ‫‪our‬‬ ‫‪ability‬‬

‫در آخر‪ ،‬هر فرماني مي‌تواند از طريق گريز با ! ‪ cmd‬در ‪ idiff‬اجرا شود‪ .‬از نظر تکنیکي‪ ،‬سخت‌ترين قسمت کار ‪ diff‬مي‌باشد و تاکنون‬

‫برای ما انجام شده است‪ .‬بنابرای‪ ،‬کار واقعي ‪ ،idiff‬تجزيه کردن خروجي ‪ diff‬و باز کردن ‪ ،‬بستن‪ ،‬خواندن و نوشتن فايلهای صحیح در‬

‫زمان درست آن مي‌باشد‪ .‬زير برنامه اصلي ‪ ،idiff‬فايلها را تنظیم مي‌کند و فرآيند ‪ diff‬را اجرا مي‌کند ‪:‬‬

‫‪/ * idiff : interactive diff * /‬‬ ‫> ‪# include < stdio . h‬‬ ‫> ‪# include < ctype . h‬‬ ‫‪char‬‬ ‫; ‪* programe‬‬ ‫‪# define HUGE 10000‬‬ ‫‪/ * large number of lines * /‬‬

‫( ‪main )argc , argv‬‬ ‫; ‪int argc‬‬ ‫; [ ] ‪char * argv‬‬ ‫}‬ ‫; ( ) ‪FILE * fin , * fout , * f 1 , * f 2 , * efopen‬‬ ‫; ( ) ‪char buf ] BUFSIZ[ , * mktemp‬‬ ‫; ‪char * diffout = ″ idiff. x x x x x x ″‬‬ ‫; [ ‪progname = argv ] 0‬‬ ‫} (‪if )argc ! = 3‬‬ ‫; (‪fprintf )stderr , ″ usage ; idiff file 1 file 2 \ n ″‬‬ ‫; (‪exit )1‬‬ ‫{‬


‫محیط برنامه سازی لینوکس‬

209/322

f1 = efopen )argv ]1[ , ″ r ″ ( ; f2 = efopen )argv ]2[ , ″ r ″ ( ; fout = efopen ) ″ idiff . out ″ , ″ w ″ (; mktemp )diffout( ; sprintf )buf , ″ diff % s > % s ″ , argv ]1[ , argv ]2[ , diffout( ; system )buf( ; fin – efopen )diffout , ″ r ″ (; idiff )f1 , f2 , fin , fout( ; unlike )diffout( ; printf ) ″ % s output in file idiff . out \ n ″ , progname ( ; exit < 01 ; { ‫ آرگومان خود را روی هم‬، mktemp .‫ متفاوت از هرگونه فايل موجود مي‌باشد‬،‫ فايلي را بوجود مي‌آورد که نامش‬، mktemp )3( ‫تابع‬ ‫ فايل‬، unlike )2( ‫ فراخوان سیستمـ‬.‫ جايگزين مي‌شوند‬،‫ و يك حرف‬idiff ‫ از فرآيندـ‬process-id ‫ توسطـ‬، x’s ‫ ششـ‬: ‫مي‌نويسدـ‬

idiff ‫ توسط يك تابع با عنوان‬،diff ‫ کار حلقه‌سازی درون تغییرات گزارش شده توسط‬.‫نامگذاری شده را از سیستم فايل پاك مي‌کند‬

،‫ از روی داده ‌های ناخواسته در يك فايل بگذريد‬،‫ را پرينت کنید‬diff ‫ يك قطعه از خروجي‬: ‫ عقیده اصلي ساده است‬.‫انجام مي‌شود‬

.‫ جزئیات يکنواخت بسیار زيادی وجود دارد‬.‫سپس نسخه مطلوب از فايل ديگر را کپي کنید‬

.‫ بسیار آسان است‬،‫ اما درك بخشهای آن‬،‫بنابراين رمز بزرگتر از چیزی است که ما مي‌خواهیم‬

idiff )f1 , f2 , fin , fout( / * process diffs * / FILE * f1 , * f2 , * fin , * fout ; } char * temfile = ″ idiff – x x x x x x ″ ; char buf ] BUFSIZ[ , buf2 ] BUFSIZ[ , * mktemp ) ( ; FILE * ft , * efopen ) ( ; int cmd , n , from1 , to 1 , from 2 , to 2 , nf1 , nf2 ;

mktemp )tempfile( ; nf1 = nf2 = 0 ; while )fgets )buf , size of buf , fin( ! = NULL( } parse )buf , $ from1 , $ from 1, $ to 1 , $ cmd , $ from 2 , $ to 2(; n = tol – from1 + to2 – from 2 + 1 ; /* # lies from diff * / if )cmd = = ′ c ′( n+=2; else if )cmd = = ′ a ′ ( from 1 + + ; else if )cmd = = ′ d ′( from 2 + + ; printf ) ″ % s ″ , buf( ; while )n - - > 0( } fgets )buf , size of buf , fin( ;


‫محیط برنامه سازی لینوکس‬

210/322

print f ) ″ % s ″ , buf ( ; { do } print f ) ″ ? ″( ; fflush )stdout( ; fgets )buf , sizeof buf , stdin( ; switch )buf ]0[ ( { case ′ > ′ : nskip )f1 , to 1 – nf1( ; n copy )f2 , to2 – nf2 , fout( ; break ; case ′ < ′ : nskip )f2 , to2 – nf2 ( ; n copy )f1 ,to1 – nf1 , fout( ; break ; case ′ e ′ : ncopy )f1 , from 1 – 1 – nf1 , fout( ; nskip )f2 , from 2 – 1 – nf2( ; ft = efopen )tempfile , ″ w ″( ; ncopy )f1 , tol + 1 – from1 , ft( ; fprintf )ft , ″ - - \ n ″( ; ncopy )f2 , to 2 + 1 – from 2 , ft (; fclose )ft ( ; sprint f )buf2 , ″ ed % s ″ , temp file(; system )buf2( ; ft = efopen )tempfile , ″ ed % s ″ , temp file( ; system )buf2( ; ft = efopen )tempfile , ″ r ″( ; ncopy )ft , MUGE , fout( ; fclose )ft(; break ; case ′ ! ′ : system )buf + 1( ; printf ) ″ ! \ n ″( ; break ; default : print f ) ″ < or > ore or ! \ n ″( ; break ; { { while )buf ]0[ ! = ′ < ′ $ $ buf ]0[ = ′ > ′ $ $ buf ]0[ ! = ′ e ′(; nf 1 = to 1 ; nf 2 = to 2 ;

{ ncopy )f1 , HUGE , fout ( ; unlike )tempfile( ;

/ * can fail on very long files * /


‫محیط برنامه سازی لینوکس‬

211/322

{ ‫ چهار شماره سطر و فرمان را استخراج‬،‫ انجام مي‌شود‬diff ‫ فرمان را انجام مي‌دهد اما کار دشوار تجزيه سطرها که توسط‬، parse ‫تابع‬ . )d ‫ يا‬a ، b ، c ‫مي‌کند (يکي از‬

.‫ مي‌تواند يك يا دو شماره سطر را در هر طرف از طرف فرمان بوجود آورد‬،diff ‫ اندکي پیچیده است چون‬، parse

parse )s , pfrom 1, pto 1 , pcmd , prom 2 , pto2( char * s ; int * pcmd , * pfrom1 , * pto1 , * pfrom2 , * pto2 ; } # define a2i )p( while )is digit )*s( ( p = 10 * )p1 + * s + + - ′o′ * prom1 = * ptol = * pfrom 2 = * pto 2 = o ; a2i ) * pfrom1 (; if )* s = = ′ , ′ ( } s++; a2i )* pto1( ; { else * pto 1 = * pfrom 1 ; * pcmd = * s + + ; a2i ) * pfrom 2( ; if )* s = = ′ , ′ ( } s++ a2i ) * pto2( ; { else * pto 2 = * pfrom 2 ; { .‫ انجام مي‌دهد‬،‫ به عدد صحیح را در چهار مکاني که رخ مي‌دهد‬Ascll ‫ تبديل ويژه ما از‬، a2i ‫درشت دستورالعمل‬

: ‫ از تعداد خاصي از سطرهای يك فايل عبور مي‌کنند و يا آنها را کپي مي‌کنند‬، ncopy ‫ و‬nskip

nskip )fin , n ( / * skip n lines of file fin * / FILE * fin ; } char buf ]BUFSIZ[ ; while )n - - > 0( fgets )buf , sizeof buf , fin( ;

{ n copy )fin , n , fout( / * copy n lines from fin to fout * / FILE * fin , * fout } char buf ]BUFSIZ[ ; while ) n - - > 0( } if )fgets )buf , sizeop buf , fin( = = null( return ; fputs )buf , fout( ; { {


‫محیط برنامه سازی لینوکس‬

‫‪212/322‬‬

‫همانطور که نشان مي‌دهد‪ ، idiff ،‬نمي‌تواند با مليمت از سیستم خارج شود‪ ،‬اگر دچار وقفه شود‪ ،‬چون ‪ ،idiff‬فايلهای متعددی را که‬

‫در ‪ tmp/‬قرار دارند‪ ،‬رها مي‌کند‪ .‬در فصل بعد‪ ،‬ما نشان مي‌دهیم که چگونه برای حذف فايلهای موقتي‪ ،‬مانند فايلهايي که در اينجا‬

‫استفاده مي‌شوند‪ ،‬از وقفه‌ها استفاده کنیم‪.‬‬

‫مشاهدة دشوار در ‪ zap‬و ‪ ، idiff‬اين است که قسمت اعظم کار سخت‪ ،‬توسط فردی ديگر انجام شده است‪ .‬اين برنامه‌ها‪ ،‬صرفا ً يك‬

‫واسطة مناسب را روی برنامه‌ای ديگر قرار مي‌دهند که اطلعات درست را محاسبه مي‌کند‪ .‬به دنبال فرصتي بودن برای ساخت بر روی‬ ‫کار فردی ديگر‪ ،‬ارزشمندتر اين است که خودتان آن را انجام دهید ـ اين يك روش ارزان قیمت و سودمندتر است‪.‬‬

‫تمرين ‪ 13‬ـ ‪ 6‬ـ يك فرمان ‪ q‬را به ‪ idiff‬اضافه کنید ‪ :‬پاسخ ‪ ،> q‬همه باقیمانده انتخابهای ‘ > ’را به طور خودکار مي‌گیرد؛ ‪ < q‬همه‬ ‫باقیماندة انتخابهای ‘ < ’ را مي‌گیرد‪.‬‬

‫تمرين ‪ 14‬ـ ‪ 6‬ـ ‪ idiff‬را به‌گونه‌ای تغییر دهیدکه همه آرگومانهای ‪ diff‬از ‪ diff‬عبورکنند؛ –‪ b‬و‪ ، h-‬احتمالً منتخب‌ها هستند‪ Idiff .‬را‬

‫به گونه‌ای تغییر هید که يك ويراستار متفاوت بتواند شناسايي شود‪ ،‬مانند‬ ‫چگونه اين دو تغییر برهم کنش دارند؟‬

‫‪idiff – eanother – editor file 1 file 2‬‬

‫‪$‬‬

‫تمرين ‪ 15‬ـ ‪ 6‬ـ برای استفاده از ‪ popen‬و ‪ pclose‬به جا ی يك فايل موقتي برای خروجي ‪ diff ، idiff‬را تغییر دهید‪ .‬چه تفاوتي در‬

‫سرعت و پیچیدگي برنامه بوجود مي‌آيد؟‬

‫تمرين ‪ 16‬ـ ‪ 6‬ـ ‪ diff‬دارای اين ويژگي مي‌باشد که اگر يکي از آرگومانهای آن‪ ،‬يك فهرست راهنما باشد‪ ،‬به جستجوی آن فهرست‬ ‫برای يك فايل با نامي شبیه آرگوماني ديگر مي‌پردازد‪ .‬اما اگر شما همین کار را با ‪ idiff‬انجام دهید‪ ،‬به شکلي عجیب خراب مي‌شود‪.‬‬

‫شرح دهید چه اتفاقي مي‌افتد و سپس آن را ثابت کنید‪.‬‬

‫‪ 9‬ت‪ 6 ‬ت‪ ‬دستيابي‪ ‬به‪ ‬محيط‬ ‫دستیابي به متغیرهای محیط شل از يك برنامه ‪ c‬آسا است و چنین چیزی گاهي اوقات مي تواند برای ساختن برنامه‌هايي موافق با‬

‫محیط‌شان و بدون نیاز به کاربرهای آنها‪ ،‬استفاده شود‪ .‬برای مثال‪ ،‬فرض کنید که شما از يك پايانه استفاده مي‌کنید که در آن اندازه پرده‬

‫نمايش بزرگتر از ‪ 24‬سطر نرمال مي‌باشد‪ .‬اگر شما بخواهید از ‪ p‬استفاده کنید و ازتوانايي‌های پايانه خود حداکثر استفاده را ببريد‪ ،‬چه‬

‫انتخابهايي برای شما وجود دارد؟ مشخص کردن اندازه پرده نمايش در هر زماني که شما از ‪ p‬استفاده مي‌کنید ‪ ،‬دشوار است ‪:‬‬

‫… ‪$ p – 36‬‬ ‫‪ :‬خود قرار دهید ‪ bin‬شما بايد همیشه يك نام شل را در‬

‫‪$ cat / usr / you / bin / p‬‬ ‫* ‪exec / usr / bin / p – 36 $‬‬ ‫‪$‬‬ ‫سومین راه حل ‪ ،‬تغییر ‪ P‬برای استفاده از يك متغیر محیط مي‌باشد که ويژگیهای پايانة شما را تعريف مي‌کند‪ .‬فرض کنید که شما متغیر‬


‫محیط برنامه سازی لینوکس‬

‫‪213/322‬‬

‫‪ PAGESIZE‬را در ‪ profile‬خود تعريف مي‌کنید ‪:‬‬

‫‪PAGESIZE = 36‬‬ ‫‪Export PAGESIZE‬‬

‫زير برنامهت (‪ ، )″ var ″ getenv‬به جستجوي محيطي براي متغيرت ‪ var‬شل مي‌پردازد و ارزش‬ ‫خود را به صورت يك رشته از كاراكترها باز مي‌گرداند و يا به صورت ‪ ،NULL‬اگر متغير تعريف‬ ‫نشود‪ .‬با توجهت ‪ ، getenv‬تغييرت ‪ ، p‬آسان است‪ .‬همه آن چيزي كه مورد نياز است‪ ،‬اضافه‬ ‫ه اصلي مي‌باشد‪.‬‬ ‫كردن يك جفت از اعلن‌ها و يك فراخواني براي ‪ getenv‬در آغاز زير برنام ‌‬ ‫‪/ * p : print input in chunks )version 3( * /‬‬ ‫……‬ ‫; ( ) ‪char * p , * getenv‬‬ ‫; [‪progname = argv ]0‬‬ ‫‪if )) p = getenv )″ PAGESIZE″ (( ! = NULL‬‬ ‫; (‪pagesize = atoi )p‬‬ ‫} (‪ ‬تتت ‪if )argc > 1 $ $1 argv ]1[ ]0[ = = ′‬‬ ‫;( [‪pagesize = atoi ) $ arg v ]1[ ]1‬‬ ‫; ‪argc - -‬‬ ‫; ‪argv + +‬‬

‫{‬ ‫……‬ ‫آرگومانهای انتخابي‪ ،‬پس از متغیر محیط پردازش مي‌شوند‪ .‬بنابراين هر اندازه آشکار از صفحه ‪ ،‬يك اندازه ناآشکار از صفحه را‬

‫نمي‌پذيرند‪.‬‬

‫تمرين ‪ 17‬ـ ‪ 6‬ـ ‪ idiff‬را به گونه‌ای تغییر دهید که به جستجوی محیط برای نام ويراستاری بپردازد که استفاده مي‌شود‪ .‬برای استفاده از‬ ‫‪ PAGESIZE ، 2‬و ‪ ، 3‬غیره را تغییر دهید‪.‬‬

‫تاريخچه‪ ‬و‪ ‬نكات‪ ‬كتاب‌شناسي‪ ‬‬ ‫کتابخانه استاندارد ‪ ، I/O‬پس از کتابخانه قابل انتقال از میك لسك ‪ ،‬توسط دنیس ريتچای‪ ،‬طراحي شد‪ .‬هدف هر دو بسته نرم افزاری‪،‬‬

‫فراهم کردن روش‌های ساده استانداردی است که برنامه‌ها بتوانند توسط آنها‪ ،‬بدون تغییر از سیستم‌های يونیکس به سیستم‌های‬

‫غیريونیکس حرکت کنند‪.‬‬

‫طرح ‪ p‬بر اساس يك برنامه از هنری اسپنسر مي‌باشد‪.‬‬

‫‪ adb‬توسط استیو بورن‪ sdb ،‬توسط هوارد کاتسف و ‪ lint‬توسط استیو جانسون نوشته شد‪.‬‬

‫‪ ،Idiff‬کما بیش بر اساس يك برنامه مي‌باشد که در اصل توسط جومارانزانو نوشته شد‪ Diff .‬خودش توسط داگ میکلوری نوشته شد‬ ‫و بر اساس الگوريتمي مي‌باشد که مستقل ً توسط هارولد استون و توسط وايني هانت و تام سیزماسنکي اختراع شد‪( .‬به کتاب « يك‬

‫الگوريتم سريع برای محاسبه طولني‌ترين نتايج عمومي» نوشته ] ‪ .w.‬هانت و ‪ G.T‬سیز مانسکي ‪ ، CACM ،‬ماه مي ‪ 1977‬مراجعه‬

‫کنید)‪ .‬الگوريتم ‪ ، diff‬در کتاب ‪ D.M‬میلکوری و ‪ W.J‬هانت با عنوان « يك الگوريتم برای مقايسه فايل متفاوت» ‪ 41 ،‬گزارش علمي‬


‫محیط برنامه سازی لینوکس‬

‫‪214/322‬‬

‫و تکنیکي بل لبز‪ ،1976 ،‬توصیف مي‌شود‪ .‬به نقل قول از میکلوری « من حداقل سه آلگوريتم کامل متفاوت را قبل از آلگوريتم نهايي‬

‫بررسي کرده‌ام‪ diff .‬يك مورد ناب و اصیل نه فقط برای تعیین صلحیت ـ محض در يك برنامه مي‌باشد‪ ،‬بلکه همچنین آن را مجدداً‬ ‫بررسي میکنید تا جايي که صحیح باشد‪».‬‬


‫محیط برنامه سازی لینوکس‬

‫‪215/322‬‬

‫‪ ‬فصل هشتم فراخوانیهاي سیستمی‬ ‫اين فصل بر پائین ترين سطح برهمکنش با سیستم عامل يونیکس تاکید دارد – فراخوانیهای سیستم ‪ .‬اين فراخوانیها‪ ،‬وروديهايکرتل‬

‫هستند آنها مسیرهای ساده ای هستندکه سیستم عامل فراهم مي کند و هر چیزديگری بر بالی آنها ساخته مي شود ‪.‬‬

‫ما بخش های متعدد مهمي را تحت پوشش قرار مي دهیم ‪.‬اولین بخش ‪ ،‬سیستم ‪ 1/0‬است ‪ ،‬زير بنايي تحت زير برنامه های کتابخانه‬

‫مانند ‪ . pntc,fopen‬ما در خصوص سیستم فايل ‪ ،‬بويژه فهرست ها و ‪ winod‬بیشتر صحبت خواهیم کرد ‪ .‬بعدا به بحث و بررسي در‬

‫خصوص فرآيندها مي پردازيم ‪ .‬چگونه برنامه ها از درون يکبرنامه اجرا مي شوند ‪.‬پس از آن ‪ ،‬ما در خصوص علمت ها و وقفه ها‬

‫صحبت مي کنیم ‪:‬‬

‫چه اتفاقي مي افتدزماني که شما کلید ‪ Delete‬را فشار مي دهید و چگونه از آن به طور معقول در يك برنامه استفاده مي کنیم ‪.‬‬

‫همانند فصل ‪ 6‬بسیاری از مثالهای ما ‪ ،‬برنامه های مفیدی هستند که بخشي از ويرايش هفتم نمي باشند ‪ .‬حتي اگر آنها مستقیما برای‬

‫شما مفید نباشند‪ ،‬شما بايد چیزی از خواندن آنها ياد بگیريد و آنها بايد ابزار مشابهي را بیان کنند که شما مي توانید برای سیستم خود‬ ‫بسازيد ‪.‬‬

‫جزئیات کامل در مورد فراخوانیهای سیستم در بخش ‪ 2‬از کتاب راهنمای برنامه نويس يونیکس وجود دارند و اين فصل ‪ ،‬مهمترين‬

‫بخشها را توصیف مي کند‪ ،‬اما در مورد تمامیت آن چیزی ارائه نمي دهد‬

‫‪ I/O 1­7‬داراي سطح پائین‪ :‬‬ ‫پائین ترين سطح ‪ ، I/O‬ورود مستقیم به سیستم عامل مي باشد ‪ .‬برنامه شما فايلها را درقطعاتي با اندازه مناسب مي خواند و مي نويسد ‪.‬‬

‫کرنل ‪ ،‬داده های شما را در قطعاتي ‪ ،‬میانگیر مي ند که طرحهای پیراموني و عملیات های برنامه ها را برروی طرحها‪ ،‬به منظور بهینه‬ ‫کردن عملکرد آزاد برای همه کاربرها تطبیق دهند ‪.‬‬

‫توصيف گران فايل‬ ‫همه ورودی و خروجي از طريق خواندن و نوشتن فايلها انجام مي شود ‪ ،‬چون همه طرحها پیراموني‪ ،‬حق پايانه شما ‪ ،‬فايلهايي در‬

‫سیستم فايل مي باشند ‪ .‬مفهوم اين عبارت اين است که يك اتصال منفرد همه ارتباط بین يك برنامه و طرحهای پیراموني را انجام مي‬ ‫دهد ‪.‬‬

‫در عمومي ترين مورد ‪ ،‬قبل از خواندن يا نوشتن يك فايل ‪ ،‬لزم است که سیستم خود را برای انجام آن ‪ ،‬مطلع سازيد ‪ ،‬فرآيندی که‬ ‫بازکردن فايل نامیده مي شود ‪.‬اگر شما قصد نوشتن بر روی يك فايل را داريد ‪ .‬بوجود آوردن آن فايل نیز مي تواند لزم باشد ‪ .‬سیستم‬

‫صحت انجام کار شما را کنترل مي کند (آيا فايل خارج مي شود ؟ آيا شما مجاز به دستیابي به آن هستید ؟) و اگر همه چیز درست‬ ‫باشد ‪ .‬يك عدد صحیح مثبت را که توصیف گر فايل نامیده مي شود ‪ ،‬باز مي گرداند ‪ .‬هر موقع که ‪ I/O‬بر روی فايل انجام شود ‪،‬‬

‫توصیف گر فايل برای شناسايي فايل ‪ ،‬به جای اسم استفاده مي شود ‪ .‬همه اطلعات در مورد يك فايل باز‪ .‬توسط سیستم حفظ مي‬


‫محیط برنامه سازی لینوکس‬

‫‪216/322‬‬

‫شود و برنامه شما ‪ ،‬فقط توسط يك توصیف گر فايل ‪ ،‬به فايل رجوع مي کند ‪ .‬يك اشاره گر ‪ FILE‬به همان صورتي که در فصل ‪6‬‬

‫توصیف شد ‪ .‬به ساختاری اشاره مي کند که در میان ساير چیزها دارای توصیف گر شد ‪ .‬به ساختاری اشاره مي کند که در میان ساير‬ ‫چیزها ‪ ،‬دارای توصیف گر فايل مي باشد ‪ ، fileno)ff( macro .‬که در >‪ <stdio.b‬تعريف مي شود ‪ .‬توصیف گر فايل را باز مي‬

‫گرداند ‪.‬‬

‫آرايش های خاصي برای مناسب ساختن ورودی وخروجي پايانه وجود دارند ‪ .‬زماني که يك برنامه توسط شل شروع مي شود‪ ،‬سه‬

‫فايل باز را با توصیف گران فايل ‪ 0,1‬و ‪ 2‬بدست آورد که ورودی استاندارد ‪ ،‬خروجي استاندارد و خطای استاندارد نامیده مي شوند ‪.‬‬

‫هر سه مورد‪ ،‬توسط پیش فرض به پايانه متصل مي شود بنابراين اگر يك برنامه فقط توصیف گر فايل ‪ 0‬را بخواند و توصیف گران فايل‬

‫‪1‬و ‪ 2‬را بخواند‪ ،‬مي تواند ‪ 1/0‬را بدون باز کردن فايلها بخواند ‪ .‬اگر برنامه فايلهای ديگر را باز کند ‪ ،‬آنها دارای توصیف گران فايل ‪3‬و‬ ‫‪ 4‬و غیره خواهند بود ‪.‬‬

‫اگر ‪ 1/0‬به سمت فايلها يا لوله ها تغییر جهت دهد و يا از آنها خارج شود ‪ ،‬شل ‪ ،‬تخصیص های پیش فرض را برای توصیف گران‬ ‫فايل ‪ 0‬و ‪ 1‬از پايانه به سمت فايلهای نام گذاری شده تغییر مي دهد‪ .‬در حالت عادی ‪ ،‬توصیف گر فايل ‪ ، 2‬متصل به پايانه باقي مي‬

‫ماند ‪ ،‬در نتیجه پیامهای خطا مي توانند به آنها بروند ‪ .‬عملکردهای شل ‪ ،‬مانند<‪ filename 2‬و ‪ ، 2 &1‬منجر به آرايشهای پیش فرضها‬

‫مي شوند ‪ ،‬اما تخصیص های فايل توسط شل تغییر مي کنند و نه توسط برنامه ‪( .‬برنامه خودش مي تواند اين تخصیص ها را مجددا‬ ‫مرتب کند ‪ ،‬اگر بخواهیم ‪ ،‬اما اين مورد نادر است ‪.‬‬

‫‪ I/O‬فايل – خواندن و نوشتن‬ ‫تمام ورودی و خروجي توسط دوفراخواني سیستم انجام مي شود ‪ write , read ،‬که از ‪ c‬توسط عملیات هايي با همین نام ‪ ،‬دستیابي‬ ‫مي شوند ‪ .‬برای هر دو‪ ،‬اولین آرگومان ‪ ،‬توصیف گر فايل است ‪ .‬دومین آرگرمان ‪ ،‬يك آرايه از بايتهايي مي باشد که به عنوان منبع يا‬ ‫مقصد داده ها ارائه مي شود ‪ .‬سومین آرکومان ‪ ،‬تعداد بايتهايي است که بايد منتقل شوند ‪.‬‬

‫;‪Int fd,n,nread , written‬‬ ‫;[‪Char buf ]SIZE‬‬ ‫;(‪Nread = read )fd,buf,n‬‬ ‫;(‪Nwritten=write )fd , buf,n‬‬ ‫هر فراخواني ‪ ،‬يك شما را از تعداد بايتهای انتقال يافته را باز مي گرداند ‪ .‬در خواندن ‪ ،‬تعداد بايتهای بازگردانده شد ‪ ،‬ممکن است کمتر‬

‫از تعداد بايتهای درخواست شده باشد ‪ ،‬چون ‪ ،‬کمتر از ‪ n‬بايت برای خواندن باقي مي ماند ‪( .‬زماني که فايل يك پايانه است ‪ red ،‬در‬

‫حالت عادی ‪ ،‬فقط تا سطر بعدی را مي خواند که معمول کمتر از چیزی است که درخواست مي شود ‪ ).‬ارزش بازگشت صفر‪ ،‬در انتهای‬ ‫فايل ايجاب مي کند و ‪ ،-1‬يك خطا را نشان مي دهد ‪ .‬برای نوشتن ‪ ،‬ارزش بازگردانده شده ‪ ،‬تعداد بايتهايي است که حقیقتا نوشته مي‬

‫شوند و يك خطا رخ مي دهد اگر اين تعداد ‪ ،‬برابر با تعداد بايتهای در نظر گرفته شده برای نوشتن نباشند ‪.‬‬

‫زماني که تعداد بايتهايي که بايد خوانده يا نوشته شوند‪ ،‬محدود نمي شود‪ ،‬عمومي ترين ارزشها ‪ ،1‬که به معنای يك کاراکتر در يك زمان‬

‫مي باشد(میانگیر نشده ) و اندازه يك بلوك بر روی يك ديسك که اغلب دارای ‪ 512‬يا ‪ 1024‬بايت مي باشد ‪( ،‬پارامتر ‪ BUFSIZ‬در‬

‫>‪ <stdio .b‬دارای اين ارزش مي باشد ) هستند ‪.‬‬

‫برای شرح ‪ ،‬در اينجا برنامه ای وجود دارد که ورودی خود را برای خروجي خود کپي مي کند ‪ .‬چون ‪ ،‬ورودی و خروجي مي توانند‬


‫محیط برنامه سازی لینوکس‬

‫‪217/322‬‬

‫برای هر فايل يا طرحي مجددا تغییر جهت دهند‪ ،‬اين برنامه ‪ ،‬حقیقتا هر چیزی را برای چیزی کپي مي کند و اين برنامه يك تحقق‬

‫چارچوب اصلي ‪ cat‬مي باشد‬

‫‪/*cat:minimal version*/‬‬ ‫‪#define SIZE 512/*arbitrary*/‬‬ ‫‪main]1‬‬ ‫‪.‬‬ ‫[‪char buf]SIZE‬‬ ‫;‪int n‬‬ ‫‪while ))n=read )0,buf , size of buf((>0‬‬ ‫;(‪write )1,buf,n‬‬ ‫; (‪exit )0‬‬ ‫اگر اندازه فايل ‪ ،‬يك مضرب از ‪ SIZE‬نباشد ‪ ،‬برخي از ‪ ، read‬تعداد کمتری از بايتهايي را که بايد توسط ‪ write‬نوشته شوند ‪ ،‬باز مي‬ ‫گرداند و فراخواني بعدی برای ‪ read‬که پس از آن ‪ ،‬صفر بر مي گردد ‪.‬‬

‫خواندن ونوشتن در قطعاتي که ديسك را تطبیق مي کنند ‪ ،‬بسیار موثر مي باشد‪ ،‬اما حتي ‪ I/O‬به صورت يك کاراکتر در يك زمان ‪،‬‬

‫برای میزان ناچیزی از مقادير داده ها ‪ ،‬امکان پذير است ‪ .‬چون کرنل ‪ ،‬داده های شما را میانگیر مي کند و ارزش اصلي ‪ ،‬فراخواني های‬

‫سیستم مي باشد ‪ .‬برای مثال ‪ ed‬از خواندن های يك بايتي برای بازيابي ورودی استاندارد آن ‪ ،‬استفاده مي کند ‪ .‬ما اين نسخه از ‪ cat‬را‬ ‫روی يك فايل با ‪ 54000‬بايت زمان داديم ‪ ،‬برای ‪ 6‬ارزش از ‪: SIZE‬‬

‫‪Vax-11.750‬‬ ‫‪8/188‬‬ ‫‪3/19‬‬ ‫‪6/2‬‬ ‫‪0/1‬‬ ‫‪6/0‬‬ ‫‪6/0‬‬

‫‪Pdp= 11.70‬‬ ‫‪0/271‬‬ ‫‪9/29‬‬ ‫‪8/3‬‬ ‫‪3/1‬‬ ‫‪2/1‬‬ ‫‪0/1‬‬

‫(‪Tim )user + system, sec‬‬

‫‪SIZE‬‬ ‫‪1‬‬ ‫‪10‬‬ ‫‪100‬‬ ‫‪512‬‬ ‫‪1024‬‬ ‫‪5120‬‬

‫اندازه بلوك ديسك ‪ 512 ،‬بايت بر روی سیستم ‪ PDP-11‬و ‪ 1024‬بايت بر روی ‪ VAX‬مي باشد ‪ .‬تقريبا برای فرآيندهای متعدد مجاز‬ ‫مي باشد که در يك زمان به يك فايل دست يابند و حقیقتا ‪ ،‬يك فرآيند مي تواند نوشته شود ‪ ،‬زماني که فرآيندی ديگر خوانده مي شود‬

‫اگر اين چیزی نباشد که شما مي خواهدی مي توان نگران کننده باشد ‪ ،‬اما گاهي اوقات مفید است ‪ .‬اگر چه ‪ ،‬يك فراخواني برای ‪read‬‬

‫‪ ،‬صفر را باز مي گرداند و در نتیجه علمت های انتهای فايل را باز مي گرداند ‪ ،‬اما اگر داده های بیشتری بر روی آن فايل نوشته شود ‪،‬‬

‫‪ read‬بعدی ‪،‬بايتهای بیشتری را در دسترس مي يابد ‪ .‬اين مشاهده ‪ ،‬مبنای برنامه ای است که ‪ redslow‬نامیده مي شود برنامه ای که‬ ‫خواندن ورودی خود را‪ ،‬بدون توجه به اين که آيا به انتهای فايل مي رسد يا نه ‪ ،‬ادامه مي دهد ‪ readslow.‬برای تماشای پیشرفت يك‬ ‫برنامه مناسب است ‪.‬‬

‫‪#slowprog > tem‬‬ ‫‪5213 process - id‬‬ ‫‪# redslow <tem: grep sometting‬‬ ‫به عبارت دير کي برنامه کند که خروجي را در يك فايل تولید مي کند ؛ ‪ readslow‬و شايد در همکاری با برنامه ای ديگر ‪ ،‬انباشته‬


‫محیط برنامه سازی لینوکس‬

‫‪218/322‬‬

‫شدن داده ها را مشاهده کند ‪.‬‬

‫از نظر ساختاری‪ redslow ،‬مشابهه با ‪ cat‬مي باشد ‪ ،‬به استثنای اينکه ‪ ،‬به جای خارج شدن از سیستم ‪ ،‬حلقه سازی مي کند ‪ ،‬زماني که‬

‫با انتهای جريان ورودی مواجه مي شودـ ‪ redslow .‬بايد ازـ ‪ I/O‬دارای سطح پائین استفاده کند ‪ ،‬چون زير برنامه های کتابخانه‬

‫استاندارد‪ ،‬پس از اولین پايان فايل ‪ EOF ،‬را گزارش مي دهند ‪.‬‬

‫‪/*readslow:keep reading, waiting for more*/‬‬ ‫‪# define SIZE 512/*arbitrary */‬‬ ‫[]‪main‬‬ ‫[‪char buf]SIZE‬‬ ‫; ‪int n‬‬ ‫}(; ;)‪for‬‬ ‫‪while ))n=read )0,buf , sizeof buf(( >01‬‬ ‫;(‪write )1,buf , n‬‬ ‫;(‪sleep )10‬‬ ‫{‬ ‫تابع ‪ sleep‬باعث مي شود که برنامه برای چند ثانیه خاص ‪ ،‬مسکوت باقي بماند و اين تابع در ‪ )sleep )3‬توصیف مي شود ‪ .‬ما نمي‬ ‫خواهیم ‪، readslow‬در فايل ‪ ،‬به خاطر جستجوی مداوم برای داده های بیشتر‪ ،‬بسته شود ‪ ،‬چون چنین چیزی در زمان ‪ cpu‬بسیار‬

‫پرهزينه خواهد بود ‪ .‬بنابراين اين نسخه ‪ ، readslow‬ورودی خود را تا انتهای فايل کپي مي کند ‪ ،‬اندکي مي خوابد و سپس دوباره‬

‫تلش مي کند ‪.‬اگر داده های بیشتری برسند ‪ ،‬زماني که اين نسخه خواب است ‪ .‬توسط ‪ read‬بعدی خوانده خواهد شد ‪.‬‬

‫تمرين ‪ . 7-1‬يك آرگومان –‪ n‬به ‪ readslow‬اضافه کنید ‪ ،‬سپس زمان خواب پیش فرض مي تواند تا ‪ n‬ثانیه تغییر کند ‪ .‬برخي از‬

‫سیستم ها يك انتخاب –‪( f‬برای همیشهـ ) برایـ ‪ tail‬تهیه مي کنند که تابعههایـ ‪ tail‬را باتابعهایـ ‪ readslow‬ترکیب مي کندـ ‪ .‬در‬ ‫خصوص اين طرح توضیح دهید ‪.‬‬

‫تمرين ‪ . 7-2‬چه اتفاقي برای ‪ readslow‬مي افتد اگر فايلي که خوانده مي شود کوتاه شود ؟چگونه شما آن را ثابت مي کنید ؟ نکته در‬ ‫خصوص ‪ fstat‬در بخش ‪ 7-3‬مطالعه کنید ‪.‬‬

‫ايجاد فايل – بازكردن ‪ ،‬ايجاد كردن ‪ ،‬بستن ‪ ،‬مواردي متفاوت‬ ‫غیر از فايلهای پیش فرض ورودی ‪،‬خروجي و خطای استاندارد ‪ ،‬شما بايد آشکارا‪ ،‬فايلها را به منظور خواندن يا نوشتن آنها بازکنید ‪ .‬دو‬ ‫فراخواني سیستم برای اين کار وجود دارند ‪. creat , open ،‬‬

‫‪ Open‬تا حدودی شبیه به ‪ fopen‬در فصل قبل مي باشد ‪ ،‬به استثنای اينکه به جای بازگرداندن يك اشاره گر فايل ‪ ،‬يك توصیف گر‬ ‫فايل را بر مي گرداند که يك ‪ int‬مي باشد ‪.‬‬

‫; ‪Char*name‬‬ ‫;‪Int fd , rwmode‬‬ ‫;(‪Fd=open )name , rwmode‬‬ ‫همانند ‪ ، fopen‬آرگومان ‪ ، name‬يك رشته کاراکتر و شامل نام فايل مي باشد ‪ .‬اما دستیابي به آرگومان ‪ mode‬متفاوت است ‪rw :‬‬

‫‪ mode‬برای خواندن صفر ‪ ،‬برای نوشتن ‪ 1‬و برای بازکردن يك فايل چه برای خواندن و چه براينوشتن ‪ 2‬مي باشد ‪ open ، 1- .‬را باز‬ ‫مي گرداند ‪ ،‬اگر خطايي رخ دهد و درغیر اين صورت يك توصیف گر بهتر فايل را باز مي گرداند ‪.‬‬

‫تلش برای بازکردن فايلي که وجود ندارد يك خطاست ‪ .‬فراخواني سیستم ‪ ، creat‬برای ايجاد فايلهای جديد و يا خواندن مجدد‬


‫محیط برنامه سازی لینوکس‬

‫‪219/322‬‬

‫فايلهای متني قبلي ‪ ،‬تهیه مي شود ‪.‬‬

‫; ‪Int perms‬‬ ‫;(‪Fd = creat )name , perms‬‬ ‫‪ ، Creat‬يك توصیف گر فايل را بر مي گرداند اگر قادر به ايجاد فايل متني با عنوان ‪ name‬باشد و اگر قادر به چنین کاری نباشد ‪-1 ،‬‬

‫را برمي گرداند ‪ .‬اگر فايل وجود نداشته باشد ‪ Creat‬آن را با اجازه های مشخص شده توسط آرگومان ‪ perms‬بوجود مي آورد ‪ .‬اگر‬ ‫فايل از قبل وجود داشته باشد ‪ Creat .‬طول آن را تا صفر کوتاه مي کند ؛ اين کار يك خطا برای ايجاد فايلي که از قبل وجود دارد ‪،‬‬

‫نمي باشد (اجازه ما ‪ ،‬تغییر نخواهد کرد ) بدون توجه به ‪ perms‬يك فايل ايجاد شده ‪ ،‬برای نوشتن باز مي باشد ‪.‬‬

‫همانگونه که در فصل ‪ 2‬توصیف شد ‪ .‬نه بیت از اطلعات پشتیباني همراه با يك فايل وجود دارند که خواندن ‪ ،‬نوشتن و اجازه اجرا را‬

‫کنترل مي کنند ‪ ،‬بنابراين يك عدد هشت هشتي سه رقمي برای مشخص کردن آنها مناسب است ‪ .‬برای مثال ‪ 0755‬خواندن ‪ .‬نوشتن‬

‫واجازه اجرا را برای مالك مشخص مي کند و نیز اجازه خواندن و اجرا کردن را برای گروه و هر کسي ديگری مشخص مي کند ‪.‬عدد‬

‫صفر اصلي را فراموش نکنید ‪ ،‬که چگونگي مشخص شدن اعداد هشت هشتي در ‪ c‬مي باشد ‪.‬‬

‫برای شرح دراينجا يك نسخه ساده شده از ‪ cp‬وجود دارد ‪ .‬سادگي اصلي آن ‪ ،‬اين است که نسخه ها فقط يك فايل را کپي مي کند و به‬

‫دومین آرگومان اجازه نمي دهد که يك فهرست باشد ‪ .‬عیب ديگر اين است که نسخه ها ‪ ،‬جوازهای فايل مبدا را حفظ نمي کند ؛ ما‬

‫نشان مي دهیم که چگونه اين مورد را چاره کنیم‪.‬‬

‫‪/*cp:minimal version*/‬‬ ‫‪#include cstdio-hs‬‬ ‫‪# define PERMS 0644 /*RW for owner , R for group , others*/‬‬ ‫; ‪char * progname‬‬ ‫‪main)arg,argv(/*cp:copy fito f2 */‬‬ ‫;‪int argc‬‬ ‫;[ ] ‪char * grgv‬‬ ‫; ‪int f1, f2 ,‬‬ ‫;[‪char buf ]BUFSIZ‬‬ ‫[‪programe = qrgv ]0‬‬ ‫(‪if )argc !=3‬‬ ‫;(‪error )usage:%s from to , progname‬‬ ‫‪if ))f 1= open )argv ]1[ , 0((=-1‬‬ ‫;([‪error )cant create %s , argv]2‬‬ ‫(‪while ))n=read )f,buf , Bufsiz((>0‬‬ ‫;(‪if )write error , )char *(0‬‬ ‫;(‪exit )0‬‬ ‫{‬ ‫ما ‪ error‬را در بخش فرعي بعد مورد بحث و بررسي قرار مي دهیم ‪.‬‬ ‫دراينجا يك محدوديت (اساسا حدود ‪ 20‬به مشاهده ‪ NOFILE‬در >‪ <sys/param.hs‬بپردازيد)‪ ،‬در تعداد فايلهايي وجود دارد که يك‬ ‫برنامه مي تواند به طور همزمان باز کند ‪ .‬بر همین اساس ‪ ،‬هر برنامه ای که قصد دارد فايلهای زيادی را پردازش کند ‪،‬بايد برای استفاده‬

‫مجدد از توصیف گران فايل آماده باشد ‪ .‬فراخواني سیستم ‪ ، close‬ارتباط بین يك اسم فايل و يك توصیف گر فايل را از بین مي برد و‬

‫توصیف گر فايل را به منظور استفاده توسط فايلي ديگر ‪ ،‬آزادمي کند ‪ .‬اتمام يك برنامه از طريق ‪ exit‬يا بازگشت از برنامه اصلي ‪ ،‬همه‬ ‫فايلهای باز را مي بندد ‪.‬‬


‫محیط برنامه سازی لینوکس‬

‫‪220/322‬‬

‫فراخواني سیستم ‪ unlike‬يك فايل را از سیستم فايل پاك مي کند ‪.‬‬ ‫پردازش خطا – ‪error‬‬ ‫فراخواني های سیستم مورد بحث واقع شده در اين بخش ‪ ،‬و در حقیقت همه فراخوانیهای سیستم مي توانند منجر به خطا شوند ‪.‬‬ ‫معمول آنها ‪ ،‬يك خطا را با برگرداندن يك ارزش ‪ -1‬نشان مي دهند ‪ .‬گاهي اوقات فهمیدن اينکه چه خطای ويژه ای رخ داده است ‪.‬‬

‫خوب است برای اين منظور همه فراخوانیهای سیستم ‪ ،‬زماني که مناسب است يك عددخطا را در يك عدد صحیح خارجي جا مي‬ ‫گذارند که ‪ error‬نامیده مي شود ‪.‬‬ ‫(معني اعداد متعدد خطا‪ ،‬در مقدمه بخش ‪ 2‬از کتاب راهنمای برنامه نويس يونیکس‪ ،‬فهرست وار بیان مي شود ) با استفاده از ‪error‬‬

‫برنامه شما برای مثال مي تواند ‪ ،‬تعیین کند که آيا تلش برای بازکردن يك فايل با شکست مواجه شده است ‪ ،‬به خاطر اينکه فايل‬ ‫وجود نداشته است و يا به خاطر اينکه شما مجاز به خواندن آن نبوده ايد ‪.‬‬

‫همچنین يك آرايه از رشته های کاراکتر ‪ sys-errlist‬وجود دارد که توسط ‪ error‬مشخص مي شود و اعداد را به يك رشته معني دار‬ ‫ترجمه مي کند ‪ .‬نسخه ‪ error‬ما ‪ ،‬از اين ساختار داده ها استفاده مي کند ‪:‬‬

‫‪Error )s1 , s2( /*print error message and die */‬‬ ‫; ‪Char * s1,*s2‬‬ ‫}‬ ‫; ‪extern int error , sys-nerr‬‬ ‫‪extern char *sys- errlist ] [ ,*progname‬‬ ‫(‪if )progname‬‬ ‫;(‪fpritf)stderr , %s , programe‬‬ ‫;(‪fprintf )stderr,s1,s2‬‬ ‫(‪if )errno>&&errno<sys-nerr‬‬ ‫;[‪fprint )stderr,)% s ( , sys-errlist]errno‬‬ ‫;(‪fprint f)stderr,in‬‬ ‫;(‪exit )1‬‬ ‫{‬ ‫‪ ، errno‬در ابتدا صفر است و بايد همیشه کمتر از ‪ sys-nerr‬باشد ‪ errno .‬برای صفر ريست نمي شود ‪ .‬زمانیکه همه چیز خوب است‬ ‫‪ .‬اما شما بايد آن را پس از هر ‪ error‬ريست کنید اگر مي خواهید برنامه خود را ادامه دهید ‪.‬‬ ‫در اينجا ‪ ،‬چگونگي آشکار پیامهای خطا با اين نسخه از ‪ cp‬وجود دارد ‪:‬‬

‫‪&cp foo bar‬‬ ‫(‪cp:cant open foo )No such file or directory‬‬

‫‪ & date>foo ;chmod o foo‬يك فايل غير قابل خواندن بسازيد‬ ‫‪& cp foobar‬‬ ‫(‪cpi : cant open foo )permission denied‬‬


‫محیط برنامه سازی لینوکس‬

‫‪221/322‬‬

‫&‬

‫دستيابي تصادفي – ‪ lseek‬‬ ‫‪ I/O‬فايل در حالت عادی تربیتي است ‪ :‬هر خواندن يا نوشتن در داخل فايل درست سپس از مورد قبلي رخ مي دهد ‪ .‬اما زماني که لزم‬ ‫است ‪ ،‬يك فايل مي تواند در يك ترتیب قراردادی خوانده يا نوشته شود ‪ .‬فراخواني سیستم ‪ ، lseek‬راهي را برای وارد شدن در يك‬ ‫فايل بودن خواندن يا نوشتن واقعي فراهم مي کند ‪.‬‬

‫; ‪Int fd , origin‬‬ ‫;()‪Long offset , pos, lseek‬‬ ‫;(‪Pos=lseek )fd , offset , origin‬‬ ‫موقعیت فعلي در فايل را که توصیف گر آن ‪ fd‬مي باشد مجبور به حرکت به سمت موقعیت ‪ offset‬مي کند ‪ ،‬که متناسب با موقعیت‬ ‫مشخص شده توسط ‪ origin‬مي باشد ‪ .‬خواندن يا نوشتن بعدی در آن موقعیت شروع مي شود ‪ origin .‬مي تواند ‪0 ،‬و ‪ 1‬يا ‪ 2‬باشد‬ ‫برای اينکه مشخص کند ‪ offset‬از آغاز ‪ ،‬از موقعیت قطعي جديد يا ‪ -1‬برای يك خطا مي باشد ‪ .‬برای مثال برای فیحصه کردن به يك‬

‫فايل ‪ ،‬قبل از نوشتن در جسجوی انتهای فايل باشید ‪:‬‬

‫برای بازگشتن به آغاز (باز پیچش) و‬ ‫برای تعیین موقعیت فعلي ‪:‬‬

‫;(‪Lseek )fd , ol,2‬‬ ‫; (‪Lseek )fd , ol ,0‬‬

‫;(‪Pos = lseek )fd,ol,1‬‬ ‫توجه داشته باشید به آرگومانـ ‪ offset : ol‬به يك عدد صحیح طولني مي باشد ‪ 1( .‬درـ ‪ lseek‬به منظور تشخیص آن از ششمین‬ ‫ويرايش سیستم فراخواني ‪ seek‬مي باشد که از اعداد صحیح کوچك استفاده مي کند ‪).‬‬

‫با ‪ : seek‬و اين امکان وجود دارد که با فايلها کم و بیش شبیه آرايه های بزرگ به قیمت دستیابي کندتر‪ ،‬برخورد کنیم ‪ .‬برای مثال ‪ ،‬تابع‬ ‫زير هر عدد از بايتها را از سرمکاني در يك فايل مي خواند ‪.‬‬

‫‪Get )fd , pos , buf , n(/*read n bytes from position pos*/‬‬ ‫;‪Int fd,n‬‬ ‫‪Long pos‬‬ ‫;‪Char*buf‬‬ ‫‪If )lseek)fd ,pos,0(=-1( /*yet to pos*/‬‬ ‫;‪Return -1‬‬ ‫‪Else‬‬ ‫;(‪Return read )fd,buf ,n‬‬ ‫{‬ ‫تمرين ‪. 7-3‬برای استفاده از يك آرگومان فايل اگر وجود دارد ‪ readslow ،‬را تغییر دهید انتخاب –‪ e‬را اضافه کنید ‪:‬‬

‫& ‪ readslow­e‬‬ ‫منجر مي شود که ‪ readslow‬در جستجوی انتهای ورودی قبل از شروع به خواندن باشد ‪ lseek .‬بر روی يك لوله چه کاری انجام مي‬

‫دهد ؟‬


‫محیط برنامه سازی لینوکس‬

‫‪222/322‬‬

‫تمرين ‪ efopen . 7-4‬از فصل ‪ 6‬برای فراخواني ‪ error‬مجددا بنويسید ‪.‬‬

‫‪ 2­7‬سيستم فايل ‪ :‬فهرست هاي راهنما‬ ‫موضوع بعدی ‪ ،‬چگونگي حرکت از طريق سلسله مراتب فهرست راهنما مي باشد ‪ .‬برای چنین چیزی در حقیقت از فراخوانیهای جديد‬

‫سیستم استفاده نمي شود ‪ ،‬فقط برخي از فراخوانیهای قبلي در يك متن جديد قرار مي گیرند ‪ .‬ما با نوشتن يك تابع باعنوان ‪spname‬‬

‫شرح مي دهیم که چگونه بر اسامي فايلهای دارای تلفظ غلط غلبه کنیم ‪ .‬تابع‬

‫;(‪N=spname )name ,new nume‬‬ ‫به جستجوی يك فايل بايك نامـ « به میزان کافي نزديكـ » به منظور نامگذاری آن مي پرداز د ‪ .‬اگر يك فايل يافت شودـ ‪ .‬درون‬

‫‪ newname‬کپي مي شود ‪ .‬ارزش ‪ n‬بازگردانده شده توسط ‪ spname ، 1-‬مي باشد اگر هیچ فايلي که به میزان کافي نزديك باشد ‪،‬‬ ‫يافت نشود ‪ .‬ارزش ‪ n 0‬مي باشد اگر يك تطبیق واقعي وجود داشته باشد و ‪ 1‬است اگر يك تصحیح ساخته شود ‪.‬‬

‫‪ Spname‬يك افزايش مناسب به فرمان ‪ P‬مي باشد ‪.‬اگر شما سعي کنید که يك فايل را تايپ کنید اما اسم آن (غلط تلفظ کنید‪ p ،‬مي‬ ‫تواند از شما سئوال کند اگر شما واقعا منظورتان چیز ديگری است ‪:‬‬

‫‪ &p/urs/.YX/comd/p/spnam.c‬اسم به مدار وحشتناك نادرست بیان شده‬ ‫‪ /usy/syc/cmd/p/spname.c:y‬تصحیح مورد قبول بیان شده‬

‫‪/*spname: return correctly spelled filename*/‬‬ ‫همانگونه که ما نوشتیم ‪ spname ،‬در هر جزء از اسم فايل ‪ ،‬سعي مي کند اشتباهاتي را که در آنها يك حرف تنها افتاده است يا اضافه‬

‫شده است يا تنها يك حرف غلط است و يا يك جفت از حروف با هم جابجا شده اند تصحیح کند و همه اين موارد در فرمان بال شرح‬ ‫داده مي شوند ‪.‬اين يك لطف برای تايپیست های شلخته است ‪.‬‬

‫قبل از نوشتن رمز‪ ،‬يك بررسي کوتاه از ساختار سیستم فايل ‪ ،‬اشکالي ندارد ‪ .‬يك فهرست راهنما‪ ،‬فايلي است که شامل يك فهرست از‬

‫اسامي فايلها و يك نشانه از جايي است که آنها قرار دارند «مکان » حقیقتا يك شاخص در جدولي ديگر مي باشد که جدول ‪ inode‬نام‬ ‫دارد ‪ inocle .‬برای يك فايل جايي است که همه اطلعات در خصوص فايل به جز اسم آن ‪ ،‬حفظ مي شود ‪ .‬يك مدخل فهرست‬

‫راهنما‪ ،‬متشکل از فقط دو مورد مي باشد ‪ .‬يك عدد ‪ inode‬و يك اسم فايل ‪ .‬تشخیص دقیق را مي توان در فايل >‪ <sys>dir.h‬پیدا‬ ‫کرد ‪:‬‬

‫‪& cat/usr/include / sys/dir.h‬‬ ‫‪#define DIRIZ 14 /*max length of file name*/‬‬ ‫‪struct direct /*structure of directory entry */‬‬ ‫}‬ ‫‪ino-td- ino; /*inode number */‬‬ ‫‪char d-name ]DIRSIZ[ ; /*file name */‬‬ ‫;{‬ ‫&‬ ‫تايپ ‪ ino-t‬يك ‪ typedef‬مي باشد که شاخص را درون جدول ‪ inode‬توصیف مي کند ‪ ، ino-t .‬به صورت يك ‪ short‬بدون علمت‬ ‫بر روی نسخه های ‪ PDP-11‬و ‪ VAX‬از سیستم مي باشد ‪ ،‬اما چنین چیزی قطعا گونه ای از اطلعات واقع شده در يك برنامه نمي‬ ‫باشد ‪ :‬بلکه بر روی يك ماشین متفاوت ‪ ،‬متفاوت مي باشد ‪ .‬از اين رو ‪ ، typedef ،‬يك مجموعه کامل از تايپ های سیستم در >‬


‫محیط برنامه سازی لینوکس‬

‫‪223/322‬‬

‫‪ <sys/types.b‬يافت مي شود ‪ ،‬جايي که بايد قبل از >‪ <sys/dir.b‬باشد ‪.‬‬

‫عملکرد ‪ ، spname‬در مسیر مستقیم است ‪ ،‬اگر چه ‪ ،‬موقعیت هايي زيادی برای رفتن به سمت راست وجود دارد ‪ .‬فرض کنید اسم‬

‫فايل ‪ d1/ d2 / f/‬مي باشد ‪ .‬عقیده اصلي ‪ ،‬جدا کردن اولین جزء(‪ )/‬مي باشد‪ ،‬سپس جستجوی فهرست راهنما‪ ،‬برای اسمي است که‬

‫نزديك به جزء بعدی (‪ )d1‬مي باشد‪ ،‬سپس جستجوی فهرست راهنما‪،‬برای چیزی نزديك ‪ d2‬مي باشد و به همین ترتیب ‪ ،‬تا جايي که‬ ‫يك تطبیق برای جزء يافت شود ‪ .‬اگر در هر مرحله به يك داوطلب قابل قبول ‪ ،‬در فهرست راهنما نباشد ‪ ،‬جستجو متوقف مي شود ‪.‬‬

‫ما اين کار را به سه تابع تقسیم کرده ايم ‪ spname‬خودش اجزاء مسیر را از هم جدا مي کند و آنها را در يك اسم فايل « تا اندازه ای‬ ‫دارای بهترين تطبیق مي سازد ‪ .‬جزء جديد ‪ mindist‬را فرامي خواند که به جستجوی يك فهرست راهنمای مشخص برای فايلي مي‬

‫پردازد که به مدلهای فعلي ها نزديك مي باشد و با استفاده از يك تابع سوم ‪ spdist‬فاصله بین دواسم را محاسبه مي کند ‪.‬‬

‫‪/*spname:return correctly spelled filename*/‬‬ ‫*‪/‬‬ ‫;‪*spname )oldname , newname(char *oldname ,*newname‬‬ ‫‪*refurns -1 if no reasonable match to oldname,‬‬ ‫‪* 0 if exat match,‬‬ ‫‪* 1 if corrected .‬‬ ‫‪* stores corrected name in newname‬‬ ‫‪*/‬‬ ‫>‪# include <sys/ types.b‬‬ ‫>‪# include <sys /dir.b‬‬ ‫(‪spname )oldname,newname‬‬ ‫;‪char*oldname,*newname‬‬ ‫}‬ ‫;[‪char *p,guess ]DIRSIZ+[, best ]DIRSIZ+1‬‬ ‫;‪char * new = newname , *old = oldname‬‬ ‫}( ; ; )‪for‬‬ ‫‪while )*old==/(/*skip slashes*/‬‬

‫;‪new++=old ++‬‬

‫‪*new =\0‬‬ ‫‪if )*old=10( /*exat or corrected */‬‬ ‫;‪return strcmp )oldname,newname( !=o‬‬ ‫‪p=guess ;/*copy next component into guess*/‬‬ ‫(‪for ); *old!=/ &&*old !=10,old ++‬‬ ‫(‪if )p<guess +DIRSIZ‬‬ ‫; ‪*P++=*old‬‬ ‫;‪*p= IO‬‬ ‫(‪if )mindist )newname , guess,best(>3‬‬ ‫‪return-1 , /*hoplless */‬‬

‫‪for )p=best ; new =p++;(/*add to‬‬

‫‪/*of newname*/‬‬ ‫{‬ ‫‪mindist)dir,guess,best(/*search dir for guess*/‬‬

‫;‪char dir,guess,*best‬‬

‫}‬ ‫‪/*set best , return distance 0003*/‬‬


‫محیط برنامه سازی لینوکس‬

224/322

int d , nd , fd; struct} ino-tino ; char name ]DIRSIZ+1[ ;/*1 more than in dir.b*/ {nbuf ; nbuf . name ]DIRSIZ[=IO ;/*+1 for terminal io */ if )dir ]0[ == 0( /*current directory */ dir =0; d=3; /*minimum distance*/ if ))fd = open)dir , 0(( == -1( return di while )read )fd,)char *(&nbuf , sizeof)structdirect((>0( if)nbuf.ino(} nd = spdist )nbuf name,guess(; if)nd<=d&nd !=3(} strcpy)best , nbuf . name(; d=nd; if )d==0( /*exct match*/ break ; { { close )fd( ; returnd ; { ‫ يك ورودی فهرست راهنما را در هر زمان‬mindist ‫ جستجو مي شود‬0 ، ‫ خالي باشد‬mindist ‫اگر نام فهرست راهنمای ارائه شده برای‬ ‫ برای محاسبه تعداد‬sizeof ‫ يك ساختار مي باشد نه يك آرايه از کاراکترها ما از‬read ‫ توجه داشته باشید که میانگیر برای‬. ‫مي خواند‬ . ‫ استفاده مي کنیم‬، ‫بايتها و حرکت آدرس به سمت يك اشاره گر کاراکتر‬

‫ صفر‬cnode ‫ اخیرا مورد استفاده نباشد (چون يك فايل حذف شده است ) در نتیجه مدخل‬، ‫اگر يك شکاف دريك فهرست راهنما‬ If )nd <=d...( ‫به جای‬ if )nd <d...(

‫ تست فاصله عبارت است از‬. ‫است و از اين موقعیت به صورت جهشي عبور مي شود‬

. ‫ مي باشد که همیشه اولین ورودی در يك فهرست راهنما است‬0 ‫ هر کاراکتر مفرد ديگری يك تطبیق بهتر از‬، ‫بنابراين‬

/*spdist : return distabce between two names*/ /* *very rough spelling metric: *o if the string are identical * 1 if the string are identical *2 if one char wrong,added or deleted *3 otherwise */ # define E& )s,t()strcmp )s,t(==0( spdist )s,t( char*s,*t;


‫محیط برنامه سازی لینوکس‬

225/322

} while )*s++==*t( if )*t++== io( return o ; /*exact matoh */ if )*--s(} if )*t(} if )s)1[&&t ]1[&&*s == t ]1[ &&*t == s]1[&&E* )S+2 , t+2(( return 1; /*transposition */ if )Ea )s+1 , t+1( return2 ; /*1 char mismatch */ { if )Ea)s+1, t(( return2; / *extra character */ { if )*t&& E&)S,t+1(( return 2; /*missing character */ return 2 ; {

: ‫ آسان است‬p ‫ ادغام تصحیح تلفظ در‬، ‫ را داريم‬spname ‫زماني که ما‬

/*p:print input in chunks )version 4 (*/ # include cstdio.bs # define PAEGSIZE 22 char *progname ; /*programname for error message */ main )argc , argv( int argc ; char*argv ] [ ; } FILE *FP,*efopen ) ( ; Int ; pagesize= PAGESIZE ; Char *p,get v ) ( , buf ]BUFSIZ[; Programe = argv]0[ ; If ))p=getenv )PAGESIZE(( !=NULL( Pagesize = atoi)p(; If )argc>1&&argv ]1[ ] 0[ == - } Pugesize = atoi)&argv ] 1[ ]0[ (; Argc --; Argv ++; { if )argc==1( print )stdin ,pagesize(; else for )I=1 , I<argc;I ++( switch )spname )argv ]I[ ( , buf((} case -1 ; /*nomatchpossible */ fp = efopen cargv ]I[ , r(; break;


‫محیط برنامه سازی لینوکس‬

‫‪226/322‬‬

‫‪casel: /*corrected */‬‬ ‫;(‪fprintf )stderr, 1 %s \, buf‬‬ ‫(‪if )ttyin ) ( ==n‬‬ ‫; ‪break‬‬ ‫; ‪argv ]I[ = buf‬‬ ‫‪/*fall through...*/‬‬ ‫‪case 0: /*exact match */‬‬ ‫;(‪fp= efopen cargv ]I[ , r‬‬ ‫;(‪print )fp,pagesize‬‬ ‫;(‪fclose )fp‬‬ ‫{‬ ‫;(‪exit )0‬‬ ‫{‬

‫تصحيح تلفظ ‪ ،‬چيزي نيست كه به صورت كوركورانه براي هر برنامه اي كه از اسامي فايلها‬ ‫استفاده مي كند ‪ ،‬بكار رود ‪ ،‬تصحيح تلفظ ‪ ،‬با ‪ p‬به خوبي كار مي كند ‪ ،‬چون ‪ p‬برهم كنش‬ ‫مي باشد ‪ ،‬اما براي برنامه هايي كه برهم كنش نمي باشند ‪ ،‬مناسب نيست ‪.‬‬

‫تمرين ‪ . 7-5‬شما چقدر مي توانید برای انتخاب بهترين تطبیق ‪ ، spname‬بر روی روشهای اکتشافي ‪ ،‬پیشرفت کنید ؟ برای مثال ‪،‬‬

‫احمقانه است که با يك فايل متطم به گونه ای برخورد کنیم که گويا يك فهرست راهنما مي باشد و چنین چیزی مي تواند با نسخه‬ ‫فعلي رخ دهد ‪.‬‬

‫تمرين ‪ . 7-6‬نام ‪ ، tx‬هر گونه ‪ tc‬را که در انتهای فهرست راهنما رخ مي دهد ‪ ،‬برای هر کاراکتر ‪ ، c‬تطبیق مي کند ‪ .‬آيا شما مي توانید‬ ‫يك ارزيابي بهتراز فاصله را اختراع کنید ؟ آن را اجرا کنید و مشاهده کنید که چگونه با کار برهای واقعي کار مي کند ‪.‬‬

‫تمرين ‪ mindist . 7-7‬در هر زمان يك مدخل از فهرست راهنما را مي خواند ‪ .‬آيا ‪ p‬به صورت هوشمندانه سريعتر اجرا مي شود ‪ ،‬اگر‬ ‫خواندن فهرست راهنما‪ ،‬در مقامات بزرگتر انجام شود‪:‬‬

‫تمرين ‪ spname . 7-8‬را به گونه ای تغییر دهید که نامي را بازگرداند که يك پیشوند از يك نام دلخواه باشد ‪ ،‬اگر تطبیق نزديکتری‬ ‫يافت نشود ‪ .‬چگونه پیوندها بايد شکسته شوند‪ ،‬اگر اسامي متعددی وجود داشته باشند که همگي پیشوند را تطبیق کنند ؟‬

‫تمرين ‪ . 7-9‬چه برنامه های ديگری ‪ ،‬مي توانند از ‪ spname‬بهره مند شوند به يك برنامه خود اتکا را طراحي کنید که تصحیح را برای‬ ‫آرگونهای خود بکار برد ‪ ،‬قبل از اينکه آنها را در طول برنامه عبور دهند ‪ ،‬مانند‬

‫&‪...fix progfilenames‬‬

‫آيا شما مي توانید يك نسخه از ‪ cd‬را بنويسید که از ‪ spname‬استفاده کند که چگونه آن را نصب مي کنید ؟‬

‫‪ 3­7‬سيستم فايل ‪ inodes  :‬‬ ‫در اين بخش به ما بحث در خصوص فراخوانیهايي از سیستم مي پردازيم که به سیستم فايل و بويژه با اطلعاتي در خصوص فايلها ‪،‬‬

‫مانند اندازه ‪ ،‬تاريخ ها ‪ ،‬اجازه ها و مواردی از قبیل مي پردازند ‪ .‬اين فراخوانیهای سیستم به شما اين امکان را مي دهند که همه‬

‫اطلعاتي را بدست آوريد که ما در خصوص آنها در فصل ‪ 2‬صحبت کرديم ‪.‬‬

‫مي خواهیم وارد خود ‪ inodes‬شويم ‪ .‬بخشي از ‪ inode‬توسط يك ساختار با عنوان ‪ stat‬توصیف مي شود که در >‪<sys /stat .b‬‬

‫تعريف مي شود ‪:‬‬


‫محیط برنامه سازی لینوکس‬

227/322

Struct stat /*structure returned by stat */

{ Dev-t Ino-t short short short short Dev-t Off-t Tim-t Time-t Time-t

St-dev; St-ino; St-mod; St-nlink; St -uid ; St-gid ; St - rder ; St - size ; St-atime; St-mtime; St-time;

/*device of inode */ /*inode number*/ /*mode bits*/ /*number of links tofile*/ /*owners u serid*/ /*owners groug id */ /*for special files*/ /*file size in characters*/ /*time file last read */ /*time file last wnttenor created*/ /*time file or inode last changed*/

{ ‫ همانگونه که‬، ‫< تعريف مي شوند‬sys/stat.b> ‫ در‬ino-t , dev-t ‫ تايپهايي مانند‬. ‫ توضیح داده مي شوند‬، ‫اکثر فايلها توسط کافت ها‬ ‫ تعاريف‬، ‫ شامل يك مجموعه از پرچم هايي است که فايل را توصیف مي کنند و برای سهولت‬st-mode ‫ ورودی‬. ‫بال توصیف شد‬

: ‫< مي باشند‬sys/stat.b> ‫پرچم نیز بخشي از فايل‬


‫محیط برنامه سازی لینوکس‬

228/322

# define s-IFMI 0170000 /*type of file */ # define S- IFDIR 0040000 /*directory */ # define S-IFCHR 0020000 /*characterspecial*/ #define S-IFDLK 0060000 /*block special*/ #define S-IFREG 0100000 /*regular*/ #define S- ISUID 0004000 /*set useridon exection/* #define S-ISGID 0002000 /*set group idon execution */ #define S-ISVTX 0001000 /*save swapped texteven after use*/ #define S-IREAD 0000400 /*read permission , owner */ #define S-IWRITE 0000200 /*write permission,owner*/ #define S-IEXEC 0000100 /*execute/search permission,owner*/ ‫ يك اسم فايل را مي‬stat . ‫ پردازش مي شود‬fstat , stat ‫ توسط يك جفت از فراخوانیهای سیستم با نامهای‬، ‫ برای يك فايل‬Inode . ) ‫ را باز مي گرداند اگر يك فقط خطا وجود داشته باشد‬-1 ‫ را برای آن فايل باز مي گرداند (يا‬inode ‫گیرد واطلعات‬

: ‫ که به اين صورت است‬،) file ‫ همان کار را از يك توصیف گر فايل برای يك فايل باز انجام مي دهد (که از يك اشاره گر‬، Fstat

Char *name; Int fd; Struct stat stbuf ; Stat )name ,& st buf(; Fstat )fd , & st buf (;

. ‫ پر مي کند‬fd ‫ برای اسم فايل و توصیف گر فايل‬inode ‫ رابا اطلعات‬stbuf ‫ساختار‬

، ‫ آغاز مي کنیم‬checkmail ‫ از‬c ‫ اکنون با يك نسخه‬. ‫ ما مي توانیم نوشتن برخي از کدهای مفید را آغاز کنیم‬، ‫با وجود همه اين حقايق‬

‫ عبارت « شما پست الکترونیکي داريو » را‬، checkmail ، ‫ اگر فايل بزرگتر شود‬. ‫برنامه ای که صندوق پستي شما را نگاه مي کند‬

‫ به خاطر اين مي باشد که شما نامه پستي را‬، ‫ از قرار معلوم‬، ‫ (اگر فايل کوتاه تر شود‬. ‫پرينت مي کند و زنگ را به صدا در مي آورد‬

‫ چنین چیزی کامل به عنوان قدم اول مناسب است و شما مي توانید ممتاز‬. ) ‫خوانده و حذف کرده ايد و پیغامي درخواست نمي شود‬ /* checkmail :watch users mailbox*/ # include <stdio .bs> # include <sys / types.bs> # include <sys/ stat-h> char * progname ; char *maildir = /usrlspool/mail , /*sys tem dependent*/ main )argc,argr( int argc; char *argv ] [ ; } struct stat buf ; char *name , * getlogin ) ( ; int lastsize=0 progname = argv ]0[ ; if ))narne = get/ogin )(( == null( error )cant get name , )char*(0(; if )chdir )maildir(== -1(

. ‫تر باشید زماني که اين برنامه کار مي کند‬


‫محیط برنامه سازی لینوکس‬

‫‪229/322‬‬

‫;( ‪error )cant cd to % s , muildir‬‬ ‫} ( ; ;) ‪for‬‬ ‫‪if )stat )name , & buf( == -1(/k no mailbox */‬‬ ‫; ‪buf.st -size =0‬‬ ‫(‪if )buf .st-size >last size‬‬ ‫;(‪fprint f)stderr,lnyou have mail loov ln‬‬ ‫;‪lastsize = buf.st - size‬‬ ‫; (‪sleep )40‬‬ ‫{‬

‫{‬ ‫تابع ‪ )getlogin )3‬اسم ‪ Login‬شما را باز مي گرداند و يا اگر نتواند ‪ null‬را باز مي گرداند ‪ chdirlkmail .‬با فراخواني سیستم ‪chdir‬‬ ‫‪ ،‬به فهرست پستي تغییر مي کند ‪ ،‬بنابراين ‪ ،‬فراخوانیهای بعدی ‪ ، stat‬نبايد هر فهرستي از ريشه را برای فهرست پستي جستجو کنند ‪.‬‬

‫شما بايد ‪ maildir‬را به گونه ای تغییر دهید که بر روی سیستم شما تصحیح شود ‪ .‬ما ‪ check mail‬را نوشتیم برای اينکه بررسي کنیم‬ ‫آيا صندوق پستي وجود ندارد ‪ ،‬چون اکثر نسخه های ‪ ، mail‬صندوق پستي را حذف مي کنند اگر خال باشد ‪ .‬ما اين برنامه را در فصل‬

‫‪ 5‬نوشتیم برای اينکه تا اندازه ای ‪ ،‬حلقه های شل را شرح دهیم ‪.‬‬

‫اين نسخه فرآيندهای متعددی را بوجود مي آورد ‪ ،‬در هر زمان که به صندوق پستي نگاه مي کند ‪ ،‬بنابراين مي تواند بیشتر از بار‬

‫سیستمي باشد که شما مي خواهید ‪ .‬نسخه ‪ c‬يك فرآيند منفرد مي باشد که يك ‪ stat‬را بر روی فايل در هر دقیقه انجام مي دهد ‪ .‬چه‬ ‫قدر اين فرآيند برای اجرای ‪ checkmail‬در زمینه درتمام زمان ‪ ،‬ارزش دارد؟ ما آن را به خوبي در يك ثانیه در هر ساعت اندازه گیری‬ ‫کرديم ‪ ،‬و میزان آن ‪ ،‬آنقدر پائین است که اهمیتي ندارد ‪.‬‬

‫‪ : SV‬يك شرح از كنترل خطا‬ ‫ما بعدا قصد داريم برنامه ای را با عنوان ‪ SV‬بنويسیم که شبیه ‪ CP‬مي باشد و يك مجموعه از فايلها را برای يك فهرست راهنما کپي‬ ‫مي کند ‪ ،‬اما هر فايل مقصد را فقط زماني تغییر مي دهد که فايل وجود ندارد و يا قديمي تر از مبدا مي باشد ‪ SV .‬برای ذخیره کردن‬

‫مي باشد ‪ .‬ايده دراينجا اين است که ‪ SV‬چیزی را که بیشتر جديد به نظر مي رسد‪ ،‬روی هم کپي نمي کند ‪ SV .‬اکثر اطلعات را در‬ ‫‪ inode‬به جای ‪ checkmail‬استفاده مي کند ‪ .‬طرحي که ما برای ‪ sv‬استفاده مي کنیم عبارت است از ‪:‬‬

‫‪& sv file 1 file 2... dir‬‬ ‫فايل ‪ 1‬را برای ‪ dir/file1‬و فايل ‪ 2‬را برای ‪ dir/file 2‬و غیره کپي مي کند ‪ ،‬به استثنای زماني که يك فايل مقصد‪ ،‬جديدتر از فايل‬ ‫مبدا آن مي باشد ‪ ،‬هیچ گونه کپي انجام نمي شود و يك اخطار پرينت مي شود ‪ .‬برای اجتناب از ايجاد کپي های متعدد از فايلهای‬

‫مرتبط ‪ sv ،‬در هیچ کدام از اسامي فايلهای مبدا به ‪ s/‬اجازه نمي دهد ‪.‬‬

‫‪/*sv: save new files */‬‬ ‫>‪# include <stdio .h‬‬ ‫>‪# include <sys/types.h‬‬ ‫>‪# include <sys/stat .h‬‬ ‫>‪# include <sys/stat .h‬‬ ‫; ‪char*programe‬‬ ‫(‪main)argc,argv‬‬


230/322

‫محیط برنامه سازی لینوکس‬

int argc; char *argv ] [ ; } int I ; struct stat stbuf ; char *dir = argv ]argc-1[ progname = argv ]0[ ; if )argv<=2( error )usage :%s files ...dir , progname(; if )stat )dir,&stbuf(== -1 error )cant access directory % s, dir(; if ))st buf.st-mode &s-ifmt(! =s-ifdir( error )%s is not a directory , dirl; for )I=1,I<argc-1 , I ++( sv)argv ]I[ , dir( ; exit )0( ; { ‫ زمانهای موجود در‬inode 0:00( ‫ از مدتها قبل برحسب ثانیه مي باشند‬GMT ‫ بنابراين فايلهای قديمي تر‬، )1970 ، ‫اول ژانويه‬ ‫ دارای ارزشهای کمتری در زمینه‬st-mtime ‫ خود مي باشند‬.

SV)file , dir( /*save file in dir*/ Char *file , * dir } struct stat sti , sto ; int fin , fout , n; char target ]BUFSIZE[ , buf ]BUFSIZ[, *index2 sprint f )target , %s/%s , dir , file( ; if )index )file , /(! =Null(/*strchrcin some systems */ error )wont handle/s in %s , file(; if )stat )file, &sti (=-1 error)can't stat %s , file( ; if )stat)target , &sto (==-1( /*target not present*/ stoost - mtime =0 ; /* somake it look old */ if )sti.st-mtime< sto .st-mtime( /*target is newer */ fprint f )stderr , % s : % s not copied\n , progname ,file ( ; else if ))fin=open )file ,0( == -1 ( error )can't open file % s , file (; else if ))fout = creat )target , stist - mode(( == -1 error )can't create % s , target(; else while ))n=read)fin , buf , sizeof buf ((>0( if )write )fout , buf , n (!= n( error )error writing % s , target(; close )fin( ; close )fout ( ; {


‫محیط برنامه سازی لینوکس‬

‫‪231/322‬‬

‫ما به جای تابعهای استاندارد ‪ I/O‬از ‪ creat‬استفاده کرديم ‪ ،‬در نتیجه ‪ sv‬مي تواند از وضعیت فايل ورودی محافظت کند ‪( .‬توجه‬

‫داشته باشید که ‪ strchr , index‬نامهای متفاوت برای يك زير برنامه مي باشند و کتاب راهنمای خود را تحت ‪ )string )3‬کنترل کنید‬ ‫برای اينکه ببنید سیستم شما از چه نامي استفاده مي کند ‪) .‬‬

‫اگر چه برنامه ‪ ، sv‬تا حدودی مشخص مي باشد ‪ ،‬اما برخي از عقايد مهم را نشان مي دهد ‪ .‬بسیاری از برنامه ها ‪« ،‬برنامه سیستم »‬

‫نمي باشند ‪ ،‬اما مي توانند از اطلعات ذکر شد ه توسط سیستم عامل استفاده کنند و به فراخواني های سیستم دست يابند ‪ .‬برای چنین‬

‫برنامه هايي لزم است که ارائه اطلعات ‪ ،‬فقط از فايلهای عنوان استاندارد مانند >‪ <dir . b‬و >‪ ، <stat.h‬ظاهر شود و اين برنامه ها‬

‫شامل آن فايلها مي باشند ‪ ،‬به جای اينکه اعلن های واقعي را در خودشان قرار دهند ‪ .‬چنین رمزی ‪ ،‬به احتمال قوی ‪ ،‬قابل انتقال از يك‬ ‫سیستم به سیستمي ديگر مي باشد ‪.‬‬

‫همچنین ارزشمند است که حداقل در سوم رمز در ‪ ، sv‬کنترل خطا باشد ‪ .‬در مراحل اولیه نوشتن يك برنامه ‪ ،‬صرفه جويي در استفاده‬

‫از خطا ‪ ،‬وسوسه انگیز مي باشد ‪ ،‬چون يك انحراف از وظیفه اصلي مي باشد ‪ .‬و زماني که برنامه کار مي کند ‪ ،‬اشتیاق در مورد برگشتن‬ ‫برای انتخاب بازبیني هايي که يك برنامه کار مي کند ‪ ،‬اشتیاق درمورد برگشتن برای انتخاب بازبیني هايي که يك برنامه خصوصي را به‬ ‫برنامه ای تبديل مي کنند که بدون توجه به اين که چه اتفاقي مي افتدکار مي کند ‪،‬دشوار است ‪.‬‬

‫‪ ، Sv‬يك شاهد در مقابل همه اشتباهات ممکن نمي باشد – ‪ sv‬در زمانهای نامناسب به وقفه های نمي پردازد – اما دقیق تر از اکثر‬

‫برنامه ها مي باشد ‪ .‬برای تمرکز بر روی فقط يك نکته در يك لحظه ‪ ،‬بیان ‪ write‬نهايي را در نظر بگیريد ‪ .‬خراب شدن ‪ write‬به‬

‫ندرت رخ مي دهد ‪ .‬بنابراين اکثر برنامه ها اين احتمال را ناديده مي گیرند ‪ .‬اما ديسکها از فضا خارج مي شوند و کاربرها ‪ ،‬پافراتر از‬

‫نقل قولها مي گذارند ؛ خطوط ارتباطات شکسته مي شود ‪ .‬همه اين موارد مي توانند منجر به خطاهای ‪ write‬شوند و شما بهتر عمل‬ ‫خواهید کرد اگر در خصوص آنها مطالبي بشنويد به جای اينکه برنامه به آرامي وانمودند که همه چیز خوب است ‪.‬‬

‫درست اين است که کنترل خطا خسته کننده اما مهم است ‪ .‬ما در اکثر برنامه های اين کتاب به خاطر محدوديتهای مکاني و تاکید بر‬

‫موضوعات جالب تر سرفراز بوده ايم ‪ .‬اما ‪ ،‬برای تولید واقعي برنامه ها ‪ ،‬شما نمي توانید خطاها را ناديده بگیريد ‪.‬‬

‫تمرين ‪ . 7-10‬برای تشخیص فرستنده پست ‪ ،‬به عنوان بخشي از پیام «شما نامه پستي داريد » ‪ chekemail‬را تغییر دهید ‪ .‬نکته‬

‫‪lseek-ss canf‬‬ ‫تمرين ‪ chekmail . 7-11‬را به گونه ای تغییر دهید که قبل از اينکه وارد حلقه خود شود ‪،‬برای فهرست پستي تغییری نکند ‪ .‬آيا اين‬

‫کار دارای اثر قابل اندازه گیری بر عملکرد خود مي باشد ؟ (سخت تر)‪ ،‬آيا شما مي توانید يك نسخه از ‪ checkmail‬را به گونه ای‬

‫بنويسید که فقط نیاز به يك فرآيند برای اطلع به همه کاربرها باشد؟‬

‫تمرين ‪ . 7-12‬يك برنامه ‪ watchfile‬به گونه ای بنويسید که يك فايل را بررسي کند و فايل را از آغاز هر زماني که تغییر مي کند ‪،‬‬ ‫پرينت کند ‪ .‬چه موقع شمامي توانید از آن استفاده کنید ؟‬

‫تمرين ‪ sv . 7-13‬در استفاده از خطای خود ‪ ،‬تقريبا سختگیر مي باشد ‪ .‬آن را به گونه ای تغییر دهید که ادامه يابد ‪ ،‬اگر نمي تواند فايلي‬ ‫را پردازش کند ‪.‬‬

‫تمرين ‪ sv . 7-14‬را بازگشتي بسازيد ‪ :‬اگر يکي از فايلهای مبدا ‪ ،‬يك فهرست راهنما باشد ‪ ،‬آن فهرست و فايل هايش به يك روش‬ ‫پردازش مي شوند ‪ cp .‬را بازگشتي بسازيد ‪ .‬بحث کنید که آيا ‪ sv,cp‬بايد يك نوع برنامه باشند ‪ ،‬در نتیجه ‪ cp-v‬کپي را انجام نمي‬ ‫دهد ‪ ،‬اگر فايل مقصد جديدتر باشد ‪.‬‬

‫تمرين ‪ . 7-15‬برنامه ‪ random‬را بنويسید ‪:‬‬


‫محیط برنامه سازی لینوکس‬

‫‪232/322‬‬

‫‪& random filename‬‬ ‫يك خط منتخب به صورت تصادفي از فايل تولید مي کند ‪ .‬با دادن اسامي افراد به فايل ‪ random ،‬مي تواند در يك برنامه با عنوان‬ ‫‪ scapeyoat‬استفاده شود ‪ ،‬برنامه ای که برای اختصاص به اشتباه ارزشمند مي باشد ‪:‬‬

‫‪& cat scapegoat‬‬ ‫! ‪echo it s all random peoples foult‬‬ ‫‪&scape goat‬‬ ‫!‪its all kens a fault‬‬ ‫&‬

‫اطمینان حاصل کنید که ‪ ، random‬بدون توجه به توزيع طول سطرها ‪ ،‬درست مي باشد ‪.‬‬

‫تمرين ‪ . 7-16‬اطلعات ديگری در ‪ inode‬نیز وجود دارد ‪ ،‬بويژه ديسك به جای نشان مي دهد که بلوکهای فايل قرار دارند ‪ .‬فايل >‬

‫‪ <sys / ino.b‬را بررسي کنید ‪ ،‬سپس برنامه ‪ icat‬که فايلهای مشخص شده توسط عدد ‪ inode‬و طرح ديسك را مي خواند ‪ ،‬را‬ ‫بنويسید ‪( .‬اين برنامه ‪ ،‬فقط زماني کار مي کند که ديسك قابل خواندن باشد ) ‪ .‬تحت چه شراي