آموزشچگونه

آموزش خط فرمان: قسمت پنجاه و ششم، ویرایش بر روی هوا (Editing on the Fly)

Print Friendly, PDF & Email

مگر می‌شود بر روی هوا هم ویرایش کرد؟ تعجب نکنید. دقیقا منظورمان همین است. تجربه ما در کار با ویرایشگرهای متنی نشان داده که این ویرایشگرها بسیار تعاملی هستند؛ بدین معنا که می‌توان مکان‌نما را به‌صورت دستی جابه‌جا نموده و سپس تغییرات خود را در آن وارد کرد.

هرچند که چندین روش غیرتعاملی برای ویرایش متن نیز وجود دارد؛ به‌عنوان مثال برای اعمال مجموعه‌ای از تغییرات بر روی چندین فایل، می‌توانیم بدون استفاده از ویرایشگرهای متنی و با یک فرمان و «بر روی هوا» انجام دهیم. در این درس به توضیح فرمان tr می‌پردازیم:

فرمان tr (بازنگاری یا حذف کاراکترها)

فرمان tr به‌منظور بازنگاری کاراکترها مورد استفاده قرار می‌گیرد. می‌توانیم آن را به‌عنوان مجموعه‌ای از عملیات مبتنی بر کاراکتر و جستجو و جایگزینی در نظر بگیریم. بازنگاری به مثابه پروسه تغییر کاراکترها از یک حرف الفبا به دیگر می‌باشد. چنین تبدیلی را می‌توان با فرمان tr به‌صورت زیر انجام داد:

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

مجموعه‌های کاراکتری را می‌توان به سه شیوه بیان کرد:

  • یک لیست شمارش شده، به‌عنوان مثال ABCDEFGHIJKLMNOPQRSTUVWXYZ.
  • محدوده‌ای از کاراکترها. به‌عنوان مثال A-Z. به یاد داشته باشید که استفاده از این شیوه، گاهی اوقات موجب ایجاد مشکلاتی برای سایر فرمان‌ها می‌شود (اشاره به ترتیب تطبیقی) در نتیجه بایستی با دقت استفاده شود.
  • کلاس‌های کاراکتری POSIX، به‌عنوان مثال [:upper:].

در اکثر موارد، مجموعه‌ای از کاراکترها، بایستی طولی برابر داشته باشند. هر چند که ممکن است مجموعه اول را با طولی بزرگ‌تر نسبت به مجموعه دوم قرار داد؛ به‌ویژه اگر بخواهیم چندین کاراکتر را به یک کاراکتر تبدیل کنیم.

فرمان tr علاوه بر بازنگری، به کاراکترها این اجازه را می‌دهد تا به‌سادگی از جریان ورودی حذف شوند. به‌عنوان مثال برای تبدیل فایل‌های متنی MS-DOS به فایل‌های متنی Unix-Style کاراکترهای return بایستی از پایان هر خط حذف شوند. این کار را می‌توان به‌صورت زیر و با استفاده از فرمان tr انجام داد:

tr -d '\r' < dos_file > unix_file

در این فرمان، dos_file می‌بایست به فایل unix_file تبدیل شود. این شکل دستوری، از توالی عبور \r برای ارایه return استفاده می‌کند. برای لیست کاملی از توالی‌ها و کلاس‌های کاراکتری، فرمان زیر را وارد کنید:

فرمان tr می‌تواند ترفند دیگری را نیز اجرا کند. فرمان tr، با استفاده از گزینه –s (سرنام واژه squeeze به‌معنای حذف) می‌تواند نمونه‌های تکرار شده از یک نمونه کاراکتر را حذف کند:

در این‌جا رشته‌ای حاوی کاراکترهای تکراری داریم. درواقع با اختصاص مجموعه ab به فرمان tr، نمونه‌های تکراری را به مجموعه خود محدود می‌کنیم؛ در حالی‌که کاراکتر c بدون تغییر باقی می‌ماند؛ چرا که در مجموعه ما نیست.

به یاد داشته باشید که کاراکترهای تکراری می‌بایست در کنار هم باشند و اگر این‌گونه نباشد، حذف صورت نخواهد پذیرفت:

فرمان sed (ویرایشگر جریان برای فیلتر کردن و انتقال متن)

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

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

در این مثال، یک جریان یک‌کلمه‌ای را با استفاده از فرمان echo ایجاد کردیم و سپس آن را به درون sed پایپ کردیم. فرمان sed در مقابل دستورالعمل s/front/back/ را بر روی متنی که در جریان وجود دارد اجرا نموده و خروجی back را ایجاد می‌کند. هم‌چنین می‌توانیم این فرمان را با استفاده از جستجو و جایگزینی vi نیز تشخیص دهیم.

فرمان‌های sed با یک کاراکتر آغاز می‌گردند. در مثال بالا، فرمان جایگزینی با استفاده از کاراکتر s ارایه شده و سپس به‌دنبال آن، رشته‌های جستجو و جایگزینی مورد نظر که با استفاده از اسلش جدا شده‌اند، آورده شده است. انتخاب کاراکتر جداکننده اختیاری است. به‌عنوان یک قانون کلی، غالبا کاراکتر اسلش (/) به‌کار برده می‌شود، ولی فرمان sed هر کاراکتر دیگری که به‌عنوان جداکننده استفاده شده باشد را قبول می‌کند.

می‌توان فرمان بالا را به‌صورت زیر نیز اجرا کرد:

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

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

ما می‌توانیم ۱ را به مثال خود اضافه کنیم:

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

اکنون می‌بینیم که ویرایش صورت نمی‌پذیرد، زیرا جریان ورودی دارای خط دومی نیست.

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

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

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

با قرار دادن عبارت منظم با جداکننده اسلش (/SUSE/)ف قادر هستیم تا خطوط حاوی آن را به همان شیوه فرمان grep ایزوله کنیم. درنهایت با اضاف کردن کاراکتر علامت تعجب (!) به آدرس، نفی را امتحان می‌کنیم:

همان‌گونه که مشاهده می‌کنید، همه موارد، غیر از مواردی که با عبات منظم مطابقت دارند، آورده شده‌اند.

تاکنون به دو فرمان ویرایشی sed (یعنی s و p) پرداختیم. جدول زیر لیست کامل‌تری از فرمان‌های ویرایشی اساسی را نشان می‌دهد:

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

در حالی‌که فرمت ما در فایل  distros.txt به‌صورت MM/DD/YYYY می‌باشد، به‌منظور آسان شدن مرتب‌سازی بهتر است که فرمت YYYY-MM-DD را داشته باشیم. به‌منظور اعمال این تغییر بر روی فایل (به‌طور دستی) زمان زیادی را باید صرف ویرایش فایل کنیم، ولی با استفاده از فرمان sed این تغییر در یک گام انجام خواهد شد:

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

sed 's/regexp/replacement/' distros.txt

گام بعدی این است که عبارت منظمی را بفهمیم که می‌تواند تاریخ را جدا کرده و دربربگیرد. از آن‌جایی‌که تاریخ در فرمت MM/DD/YYYY می‌باشد و در آخر خط مشخص شده، می‌توانیم از یک عبارت به شکل زیر استفاده کنیم:

[۰-۹]{۲}/[۰-۹]{۲}/[۰-۹]{۴}$

که این عبارت، به ترتیب دو رقم، یک اسلش (/)، دو رقم، یک اسلش (/)، چهار رقم و در آخر هم علامت $ پایان خط را نمایش می‌دهد. پس این عبارت طولانی را در جایگاه regexp قرار می‌دهیم. حال، replacement یا همان عبارت جایگزین چه می‌شود؟

برای آن‌که آن را فراهم کنیم، ابتدا بایستی با یک ویژگی جدید در عبارت منظم آشنا شوید که در برخی از اپلیکیشن‌هایی که از BRE استفاده می‌کنند، نمایان می‌شود. این ویژگی را book reference (به‌معنای مرجع کتاب) می‌نامند و به این‌صورت کار می‌کند که اگر توالی \n در جایگاه replacement پدیدار شود (که در آن n رقمی مابین صفر تا ۹ است) توالی به زیرعبارت متناظر در عبارت منظم قبلی اشاره می‌کند. برای ایجاد این زیرعبارت، به‌سادگی آن‌ها را با پرانتزهایی محصور می‌کنیم:

([۰\۹]{۲})/([۰-۹]{۲})/([۰-۹]{۴})$

اکنون سه زیرعبارت داریم. اولی شامل ماه، دومی شامل روز و سومی شامل سال است. حال، می‌توانیم جایگزین (replacement) را به‌صورت زیر بنا کنیم:

\۳-\۱-\۲

که به ترتیب به ما سال، یک کاراکتر دش (-)، ماه، یک کاراکتر دش (-) و روز را می‌دهد. اکنون فرمان به این صورت می‌باشد:

sed 's/([0-9]{2})/([0-9]{2})/([0-9]{4})$/\3-\1-\2/' distros.txt

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

sed 's/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/' distros.txt

ویژگی دیگر فرمان s، استفاده از پرچم‌های (flags) اختیاری است که ممکن است به‌دنبال رشته جایگزین یابند. مهمترین این پرچم‌ها، پرچم g بوده که به sed فرمان می‌دهد که جستجو و جایگزینی را بر روی یک خط به‌صورت سراسری انجام دهد؛ نه فقط بر روی نمونه اول که پیش‌فرض است.

این هم یک مثال:

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

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

در این گزارش کلیه نام‌های توزیع‌ها به حروف بزرگ تبدیل می‌شوند. برای انجام این کار، بایستی یک اسکریپت بنویسیم، به‌همین منظور ویرایشگر متن را گشوده و کد زیر را در فایل اسکریپت واردکرده، Ctrl+X، سپس Y و در نهایت Enter را فشار داده تا فایل ذخیره گردد. اکنون یک فایل اسکریپت با نام distros.sed ایجاد کردیم:

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

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

خط اول، کامنت (Comment) بوده و توضیحی را در رابطه با فرمان می‌دهد. خط دوم خالی است. خطوط سوم تا ششم، حاوی متنی است که بایستی درون آدرس ۱ اولین خط ورودی درج شود. فرمان i و به‌دنبال آن توالی بک‌اسلش (\). خط هفتم فرمان جستجو و جایگزینی ما بوده و درنهایت خط هشتم بازنگاری را بر روی حروف بزرگ انجام می‌دهد.

منبع: کتاب The Linux Command Line نوشته William E. Shotts

Related Articles

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

Close