
در آموزشهای پیش رو ابزارهایی را استفاده خواهیم کرد که با استفاده از آنها میتوان متن را دستکاری کرد.
همانطور که پیشتر عنوان شد، داده متنی، نقش بسیار مهمی را در سیستمهای یونیکس ایفا میکند؛ ولی قبل از آنکه بتوانیک از تمامی ویژگیهایی که توسط این ابزارها ارایه شده استفاده نماییم، میبایست تکنولوژی پیچیدهای که در این ابزارها بهکار رفته را بشناسیم، که آن را عبارات منظم (Regular Expressions) مینامند.
عبارات منظم (Regular Expressions)
عبارات منظم (Regular Expressions) نشانههای سمبولیکی هستند که بهمنظور شناسایی الگوها در متن استفاده میشوند. عبارات منظم از برخی جهات، شبیه wildcardهای Shell هستند؛ چرا که آنها نیز فایل و نام مسیر (pathname) را (در مقیاسی بزرگتر) مطابقت میدهند.
عبارات منظم توسط بسیاری از ابزارهای خط فرمان و همچنین بیشتر زبانهای برنامهنویسی، بهمنظور سهولت راهکارهای دستکاری مشکلات متن پشتیبانی میشوند.
شایان ذکر است که همه عبارات منظم در ابزارهای مختلف و زبانهای برنامهنویسی مختلف، متفاوت عمل میکنند. در این آموزش، فقط به عبارات منظم تحت استاندارد POSIX (که اکثر ابزارهای خط فرمان را پوشش میدهد)، پرداختهایم.
فرمان grep (جستجو در میان متن)
برنامه اصلی که ما از آن بهمنظور کار با عبارات منظم استفاده خواهیم کرد، grep خواهد بود. در واقع نام grep برگرفته از عبارت Global Regular Expression Print به معنای «چاپ عبارت منظم سراسری» گرفته شده است. برنامه grep فایلهای متنی را برای وجود یک عبارت منظم جستجو کرده و هر خطی که دارای عبارت منظم تعیین شده، باشد را در استاندارد خروجی چاپ مینماید.
در مثال زیر، فرمان grep با رشتههای معین استفاده شده است:
این فرمان، همه فایلهای موجود در دایرکتوری /usr/bin که شامل نام رشته zip هستند را لیست میکند. فرمان grep گزینهها و آرگومانها را به این صورت قبول میکند:
grep [options] regex [file...]
که در فرمان فوق بهجای regex عبارت منظم مربوطه قرار خواهد گرفت:
در جدول زیر گزینههای رایج grep لیست شده است:
بهمنظور توصیف کاملتر فرمان grep چند فایل متنی برای جستجو ایجاد میکنیم:
در ادامه میتوانیم جستجوی سادهای از لیست فایلها را به این صورت نیز انجام دهیم:
در این مثال، grep همه فایلهای لیست شده را برای رشته bzip جستجو میکند و دو مورد تطبیق را پیدا میکند که هر دو مورد درون فایل dirlist-bin.txt موجودند. اگر بخواهیم بهجای لیست موارد تطبیق، فقط فایلهای مربوطه را لیست نماییم، میتوانیم از گزینه –l استفاده کنیم:
در مقابل، اگر بخواهیم لیستی از فقط فایلهایی که با مورد ما مطابقت ندارند را ببینیم، میتوانیم از فرمان زیر استفاده کنیم:
متاکاراکترها و لیترالها (Metacharacters and Literals)
شاید مشخص نبود، ولی جستجوهای grep ما از عبارات منظم سادهای استفاده میکردند. با این همه، مثالهای سادهای بودند. عبارت منظم bzip بهصورتی عمل میکند که حداقل چهار کاراکتر b، z، i و p جایی درون یک خط به ترتیب ذکر شده و بدن هیچ کاراکتری مابین آنها (یعنی بهصورت bzip) یافت شوند.
کاراکترهای موجود در رشته bzip کاراکترهای لیترال (Literal) هستند، به این صورت که آنها با خودشان تطبیق داده میشوند. ممکن است عبارات منظم، علاوه بر کاراکترهای لیترال، حاوی متاکاراکترها نیز باشند. بدین صورت که آنها میتوان بهمنظور مطابقتهای پیچیدهتر مورد استفاده قرار داد. متاکاراکترهای عبارات منظم شامل موارد زیر هستند:
^ $ . [ ] { } - ? * + ( ) | \
مابقی کاراکترها را کاراکترهای لیترال (Literal) در نظر میگیرند.
البته کاراکتر بکاسلش (\) در برخی موارد برای ایجاد metasequenceها استفاده میشود و همچنین متاکاراکترها را قادر میسازد تا بهعنوان کاراکترهای لیترال (بهجای اینکه بهعنوان یک متاکاراکتر تفسیر شوند) رفتار کنند.
نکته: همانطور که میبینیم، بسیاری از عبارات منظم حاوی متاکاراکترها را در خط فرمان بهکار میبریم، حتما بایستی برای جلوگیری از بسط آنها را داخل کوتیشن قرار دهیم.
کاراکتر همه (The Any Character)
اولین متاکاراکتری که آن را بررسی میکنیم کاراکتر dot یا همان نقطه (.) است که بهمنظور مطابقت همه کاراکترها استفاده میشود. اگر که آن را در یک عبارت منظم قرار دهیم، موجب تطبیق هر کاراکتری در آن موقعیت کاراکتری میشود.
مثال زیر گویای همه چیز است:
در این مثال، ما بهدنبال هر خطی در فایلهای خود میگردیم که با عبارت منظم .zip مطابقت دارد. توجه کنید که در نتایج، برنامه zip پیدا نشد! به این دلیل که قرار دادن متاکاراکتر نقطه در عبارت منظم، طول مورد نیاز برای مطابقت را به چهار کاراکتر افزایش میدهد و از آنجایی که zip فقط سه کاراکتر دارد، مطابقت پیدا نمیکند.
همچنین اگر فایلی در لیستهای ما دارای پسوند .zip باشد تطبیق داده میشود؛ چرا که کاراکتر نقطه، در پسوند فایل نیز بهعنوان کاراکتر همه (any) رفتار میکند.
لنگرها (Anchors)
کاراکترهای caret (یا همان ^) و دلار ($)، کاراکترهایی هستند که در داخل عبارت منظم، بهعنوان یک لنگر رفتار میکنند. این بدان معنا است که این مطابقت فقط زمانی رخ میدهد که عبارت منظم، در ابتدای خط (^) و یا در آخر خط ($) پیدا شود:
در اینجا لیست فایلهایی را برای رشته zip که در ابتدای خط، انتهای خط و در هر دو موقعیت ابتدا و انتهای خط بهکار رفته است را جستجو نمودیم. به نتایج دقت کرده و موقعیت رشته zip را مشاهده کنید.
عبارات براکت و کلاسهای کاراکتر (Bracket Expressions and Character Classes)
علاوه بر مطابقت هر کاراکتری در یک موقعیت در عبارت منظم، میتوانیم کاراکتری را (با استفاده از عبارتهای براکت) از یک مجموعه کاراکتر تعیین شده، تطبیق دهیم. با عبارتهای براکت (Bracket Expressions) میتوانیم مجموعهای کاراکترها را (شامل کاراکترهایی که غیر از این بهعنوان متاکاراکترها تفسیر میشوند) برای تطبیق اختصاص دهیم. در این مثال با استفاده از یک مجموعه دو کاراکتری، هر خطی که حاوی رشته bzip یا gzip است را تطبیق میدهیم:
یک مجموعه ممکن است حاوی تعدادی از کاراکترها و متاکاراکترها باشد که وقتی در داخل براکتها قرار میگیرند، معنی خود را از دست میدهند. هر چند دو مورد وجود دارد که در آنها متاکاراکترها درون عبارات براکت استفاده شدهاند و معنای متفاوتی دارند. اولین آنها کاراکتر (^) بوده که به منظور نشان دادن نفی به کار میرود و دومین آنها کاراکتر (-) بوده به منظور نشان دادن یک محدوده کاراکتری، مورد استفاده قرار میگیرد.
کاراکتر نفی (Negation)
اولین کاراکتر در یک عبارت براکت، کاراکتر (^) است و بقیه کاراکترها مجموعه کاراکترهایی هستند که نبایستی در موقعیت کاراکتری داده شده قرار بگیذند. این کار را با ویرایش قبلی خود انجام میدهیم:
با فعال شدن نفی، لیستی از فایلهایی که حاوی رشته zip هستند را به جز آنهایی که دارای کاراکتر b یا g هستند را دریافت میکنیم. توجه داشته باشید که فایل zip پیدا نشد. مجموعه کاراکتر نفی شده هنوز نیازمند یک کاراکتر در موقعیت داده شده میباشد ولی کاراکتر نباید عضوی از مجموعه کاراکتر نفی شده باشد.
کاراکتر (^) فقط در صورتی نفی را فراخوانی میکند که اولین کاراکتر، در داخل یک عبارت براکت باشد. در غیر اینصورت مفهوم خاص خود را از دست میدهد و به یک کاراکتر معمولی در یک مجموعه تبدیل میشود.
محدودههای معمول کاراکتر (Traditional Character Ranges)
اگر که بخواهیم عبارت منظمی ایجاد کنیم که در آن هر فایلی که نام آن با یک حرف بزرگ شروع میشود را پیدا کند، میتوانیم بهصورت زیر عمل کنیم:
نیازی به این همه شلوغکاری نیست! کافی است که محدوده مورد نظر را با علامت (-) بهصورت زیر از هم جدا کنیم:
با بهکار بردن محدوده سه کاراکتری، میتوانیم ۲۶ کاراکتر را خلاصه کنیم. هر محدوده از کاراکترها را میتوان به این شیوه بیان کرد، شامل محدودههایی مثل این عبارت که همه نامهای فایلی که با حروف و اعداد شروع میشوند را شامل میشود:
در محدودههای کاراکتری، میبینیم که کاراکتر (-) به صورت ویژه رفتار میکند؛ حال چگونه یک کاراکتر (-) را در عبارت براکت قرار دهیم؟
به این صورت که آن را بهعنوان اولین کاراکتر در عبارت قرار میدهیم. مورد زیر را فرض کنید:
این مورد هر نام فایلی که حاوی یک حرف بزرگ است را تطبیق میدهد ولی از سوی دیگر:
این مورد هر نام فایلی که حاوی یک علامت (-)، یک حرف A (بهصورت بزرگ) و یک حرف Z (بهصورت کوچک) است را تطبیق میدهد.
منبع: کتاب The Linux Command Line نوشته William E. Shotts