چندین سال است که در خط فرمان از فرمانهایی استفاده میشود که مباحثی در زمینه عدم استفاده آنها مطرح است که به شرح ذیل لیست میشوند:
-
این دستورات قدیمی شدهاند.
-
چرا خط فرمان
-
مباحث new shell programming که خود به صورت یک پارادایم مطرح است.
فعلاً به همین مباحث بالا بسنده میکنیم و به آنها جواب میدهیم.
-
شاید ظاهر این دستورات قدیمی شده باشند، ولی کد این دستورات به روز میباشند. و چیزی که مهم است کد آنهاست. درواقع دستورات، یکسری interface میباشند.
-
اصولاً سوییچ کردن بین صفحهکلید و ماوس سرعت را میگیرد و این اصل، یکی از عمده دلایلیست که کاربران از خط فرمان استفاده میکنند. اما دلایل دیگری نیز وجود دارد، به عنوان مثال فرمانهایی در Unix وجود دارد که نمیتوان از قدرت آنها صرف نظر کرد و به همین دلایل کاربران خط فرمان را ترجیح میدهند.
-
واژه new shell programming کمی گنگ به نظر میرسد. اما بحثی است که چند سالیست باب شده و به مباحثی همانند customize کردن shell programming ، عدم استفاده از ترفندهای قدیمی درshell programming را شامل میشود. البته کمی با قسمت اول در ارتباط است و آن هم بهینه کردن کدها میباشد.
مثالهایی از فرمان sed
قرار نیست در این مطلب فرمان sed رو یاد بدم،کلی مطلب و مرجع در اینترنت وجود داره که چرخ از اول ساختن است. اگر sed میدانید این مطلب را نخوانید و این مطلب صرفاً برای خوانندگان تازهکار است.
سعی کردم در این مطلب چندین مثال بیارم تا با مثال خوانندگان محترم sed رو درک کنند.
خیلی از دستورات را در find حل میکنیم، به دستور زیر دقت فرمایید:
1 |
find . -type f -name "*road*" -exec sed -i 's/foo/bar/g' {} + |
نکته: وقتی از exec- استفاده مینماییم میتوان خروجی find را به صورت آرگومانی که به {} مشخص میشود به ورودی یک فرمان داد.
نکته: اگر از i- استفاده شود خروجی را مستقیماً در فایل درج میکند. اینجا نیاز بوده و درج میکنیم. اما در اکثر اوقات خروجی خود sed را باید pipe کرد.
نکته: هرجا به عبارت foo در فایلهایی که در آنها road وجود داشته باشند، آنها را به bar تبدیل میکند و در همان فایل درج میکند.
نکته: + آخر find نشان POSIX بودن استفاده کردن آن است. Old format آن به صورت زیر است:
1 |
$find . -type f -name "*road*" -exec sed -i 's/foo/bar/g' {} \; |
توصیه میشود از نوع اول استفاده شود، زیرا در برخی عبارات دچار مشکل میشوید.
نکته: در مورد فرمان find توصیه میشود یک راهنما بخوانید که هر روزه به کارتان میاید، مطلب بعدیم در مورد find میباشد.
خیلی اوقات با مشکل زیر در فرمان ssh برخورد کردهایم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ ssh mohsen@192.168.0.100 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that the RSA host key has just been changed. The fingerprint for the RSA key sent by the remote host is 3f:1b:f4:bd:c5:aa:c1:1f:bf:4e:2e:cf:53:fa:d8:59. Please contact your system administrator. Add correct host key in /home/mohsen/.ssh/known_hosts to get rid of this message. Offending key in /home/mohsen/.ssh/known_hosts:3 RSA host key for 192.168.0.100 has changed and you have requested strict checking. Host key verification failed.$ |
چیزی که در بالا دیده شد با یک دستور sed قابل حل میباشد:
1 |
$sed -i -e '3d' ~/.ssh/known_hosts |
فرمان فوق خط سوم فایل home/mohsen/.ssh/known_hosts/ را پاک میکند.
نکته: e- یک اسکریپت sed را اجرا میکند. شما میتوانید با یک sed چندین e- داشته باشید.
حال با عملگر d آشنا شدید بیایید یک سناریو با دادههای زیاد ولی متغیر تعریف کنیم، فرض کنید شما دادههایی دارید که خط آخرش معلوم نیست کدامین خط است. و از طرفی باید در یک Pipe آن خط را فیلتر کنید. به فرمان زیر نگاه کنید:
1 |
$foo |sed -e '$d' |bar |
وقتی فرمان foo یکسری داده تولید میکند، به sed پایپ شده و خط آخر آن از بین میرود و دست آخر به bar پایپ میشود.
اگر به خاطر داشته باشید فرمان tr میتوانست lowercase را به uppercase و بالعکس تبدیل نماید. به عبارت زیر دقت نمایید:
1 |
$echo 0x34fdf |sed -e '/0x[0-9a-zA-Z]*/ y/abcdef/ABCDEF/' |
کل سناریو اینگونه است که میخواهید یک عدد هگزادسیمال را به حروف بزرگ تبدیل نمایید. درست حدس زدید. عملگر y کار تبدیل را انجام میدهد.
خروجی عبارت بالا چنین میشود:
1 |
0x34FDF |
بیایید کمی فرمان فوق را دست کاری کنیم:
1 |
$echo 0x34fdf |sed -e '/0x[0-9a-zA-Z]*/ y/ABCDEF/abcdef/' |
در مبدل y جای حروف کوچک و بزرگ را عوض کردیم و نتیجه چنین شد:
1 |
0x34fdf |
اصولاً خیلی از man page ها بزرگ هستند و برای دسترسی به قسمتی از آنها باید scroll down نمود. برای حل این مشکل sed به کمکمان میآید. فرض کنید از man page بزرگ bash که خود یک کتاب است به قسمتی خاص دسترسی پیدا کنید، فرض کنید میخواهید به فرمان eval که یک فرمان built-in است دسترسی پیدا کنید. میتوانید از دستور زیر استفاده نمایید:
1 2 3 |
$man bash | sed -ne '/^ *eval/,/^$/p' eval [arg ...] The args are read and concatenated together into a single command. This command is then read and executed by the shell, and its exit status is returned as the value of eval. If there are no args, or only null arguments, eval returns 0. |
نکته: n- در حالت silent عمل میکند و چیزی چاپ نمیکند.
فایلی را در نظر بگیرید که محتویات زیر را داراست:
1 2 3 4 5 6 7 8 |
mohsen ali soosan mohsen samane rose mohsen sadaf |
نیاز دارید تا در تمام خطوطی که mohsen وجود دارد e را به o تبدیل کنید. در نظر داشته باشید که در خطوط دیگر هم e وجود دارد:
1 2 3 4 5 6 7 8 9 |
$sed -e '/mohsen/s/e/o/g' f1.txt mohson ali soosan mohson samane rose mohson sadaf |
نکته: درواقع قبل از /s یک pattern برای جستجو به sed میدهیم. و فقط در همان خطوط تغییر ایجاد میکند.
فرض میکنیم که شماره خطی را به صورت مستقیم برای تغییر دارا هستیم. بدون منظور برای تغییر در خط مذکور چنین میکنیم:
1 2 3 4 5 6 7 8 9 |
$sed -e '3s/oo/u/' f1.txt mohsen ali susan mohsen samane rose mohsen sadaf |
چندین نوع آدرسدهی در sed وجود دارد، مثال قبل یک نوع آدرس دهی بود. زمانی شما نیاز دارید تا در یک خط، نه تعدد خطوط، به sed بگویید تا تغییر بر روی کدام match روی دهد به عبارت زیر دقت کنید:
1 2 |
$echo sasanian |sed -e 's/s/m/2' samanian |
به sed گفتیم تا برروی دومین match تغییر را اعمال کنید.
وقتی میخواهیم comment های اول هر خط (#) را پاک کند باید از فرمان زیر استفاده کنیم:
1 |
$sed -e 's/^#.\(.*\)/\1/' yourfile |
با فرمان زیر عکس فرمان بالا را انجام میدهیم و بر روی هر خط comment میگذاریم:
1 2 3 4 5 6 7 8 |
$sed -e 's/^/#/' f1.txt #mohsen #ali #soosan #mohsen #samane #rose #mohsen |
اگر نیازمندید به انتهای متن چیزی اضافه کنید، باید از فرمان زیر استفاده کنید:
1 2 3 4 5 6 7 8 9 |
$sed -e "s/$/@/" f1.txt mohsen@ ali@ soosan@ mohsen@ samane@ rose@ mohsen@ sadaf@ |
همانطور که دیدید، @ به انتهای هر متن اضافه شد.
زین پس یادگیری sed به خود خواننده محترم واگذارده میشود. امیدوارم این مثالها مفید واقع شوند.