مقدمه

تا اینجا با ابزارهایی مانند grep و awk برای جستجوی الگوهای متنی ساده کار کرده‌ایم. برای مثال، ما می‌توانیم تمام خطوطی که حاوی کلمه‌ی دقیق "error" هستند را پیدا کنیم. اما اگر بخواهیم الگوهای پیچیده‌تری را جستجو کنیم چه؟ مثلاً «تمام خطوطی که با یک عدد شروع می‌شوند» یا «تمام خطوطی که حاوی یک آدرس ایمیل معتبر هستند».

اینجاست که عبارات باقاعده (Regular Expressions) یا به اختصار Regex وارد عمل می‌شوند. Regex یک زبان کوچک و بسیار قدرتمند برای توصیف الگوهای متنی است. با یادگیری Regex، شما می‌توانید الگوهای جستجوی بسیار دقیق و پیچیده‌ای بسازید. تقریباً تمام ابزارهای پردازش متن در لینوکس (مانند grep، awk، sed و حتی ویرایشگرهایی مثل Vim) از Regex پشتیبانی می‌کنند و این مهارت، قدرت شما را در خط فرمان چندین برابر می‌کند.

فراداده‌ها: بلوک‌های سازنده‌ی Regex

جادوی Regex در استفاده از کاراکترهای خاصی به نام فراداده (Metacharacters) نهفته است. این کاراکترها به جای خودشان، مفهوم یا الگوی خاصی را نمایندگی می‌کنند. در ادامه با چند مورد از اصلی‌ترین فراداده‌ها آشنا می‌شویم.

فراداده توضیح مثال
. نقطه (Dot) با هر کاراکتر تکی مطابقت پیدا می‌کند (به جز کاراکتر خط جدید).
^ لنگر شروع (Start Anchor) موقعیت ابتدای خط را مشخص می‌کند.
$ لنگر پایان (End Anchor) موقعیت انتهای خط را مشخص می‌کند.
* ستاره (Asterisk) با صفر یا چند بار تکرار کاراکتر یا گروه قبلی خود مطابقت پیدا می‌کند.
[] کلاس کاراکتر (Character Class) با هر کاراکتر تکی که درون براکت‌ها مشخص شده باشد، مطابقت پیدا می‌کند. (مثلاً [abc] یا [0-9])
\ بک‌اسلش (Escape) معنی خاص یک فراداده را از بین می‌برد و آن را به یک کاراکتر عادی تبدیل می‌کند. (مثلاً \. یعنی خود کاراکتر نقطه)

استفاده عملی از Regex با grep

بهترین راه برای یادگیری Regex، استفاده عملی از آن است. بیایید ببینیم چگونه می‌توانیم این فراداده‌ها را با دستور grep به کار بگیریم.

مثال ۱: استفاده از لنگرها (^ و $)

لنگرها به ما اجازه می‌دهند الگو را به ابتدا یا انتهای خط مقید کنیم. دستور زیر تمام خطوطی از فایل /etc/passwd را پیدا می‌کند که دقیقاً با کلمه root شروع می‌شوند:

$ grep "^root" /etc/passwd
root:x:0:0:root:/root:/bin/bash

و دستور بعدی، کاربرانی را پیدا می‌کند که شل آن‌ها /bin/bash است، یعنی خط مربوط به آن‌ها به این عبارت ختم می‌شود:

$ grep "/bin/bash$" /etc/passwd
root:x:0:0:root:/root:/bin/bash
me:x:1000:1000:me,,,:/home/me:/bin/bash

مثال ۲: استفاده از کلاس کاراکتر ([])

کلاس کاراکتر برای مشخص کردن مجموعه‌ای از کاراکترهای مجاز استفاده می‌شود. فرض کنید می‌خواهیم خطوطی را پیدا کنیم که حاوی "gray" یا "grey" هستند. می‌توانیم بنویسیم:

$ grep "gr[ae]y" somefile.txt

در این الگو، بخش [ae] به grep می‌گوید که در این موقعیت، کاراکتر a یا e قابل قبول است.

مثال ۳: استفاده از نقطه (.)

نقطه نماینده‌ی هر کاراکتر تکی است. الگوی 'c.t' با "cat"، "cot" و حتی "c_t" مطابقت پیدا می‌کند. استفاده از نقل قول دور الگوهایی که حاوی فراداده هستند، کار خوبی است تا از تفسیر آن‌ها توسط شل جلوگیری شود.

عبارات باقاعده پایه و توسعه‌یافته

دو «گویش» اصلی از Regex در خط فرمان لینوکس وجود دارد: عبارات باقاعده پایه (Basic Regular Expressions - BRE) و عبارات باقاعده توسعه‌یافته (Extended Regular Expressions - ERE).

  • BRE: این گویش قدیمی‌تر است و به طور پیش‌فرض توسط grep استفاده می‌شود. در این حالت، برخی فراداده‌های قدرتمند مانند +، ? و | معنای خاصی ندارند مگر اینکه قبل از آن‌ها یک بک‌اسلش (\) قرار گیرد.
  • ERE: این گویش مدرن‌تر و خواناتر است. در این حالت، فراداده‌های بیشتری به طور مستقیم کار می‌کنند.

برای اینکه به grep بگوییم از گویش ERE استفاده کند، باید از گزینه‌ی -E استفاده کنیم (یا مستقیماً از دستور egrep که معمولاً معادل grep -E است).

فراداده‌های قدرتمند در ERE

گویش ERE چند فراداده بسیار مفید را در اختیار ما قرار می‌دهد:

فراداده توضیح
+ با یک یا چند بار تکرار کاراکتر یا گروه قبلی مطابقت پیدا می‌کند.
? با صفر یا یک بار تکرار کاراکتر یا گروه قبلی مطابقت پیدا می‌کند (یعنی آن را اختیاری می‌کند).
| به عنوان عملگر "یا" (OR) عمل می‌کند. cat|dog با "cat" یا "dog" مطابقت دارد.
() برای گروه‌بندی عبارات استفاده می‌شود تا بتوان روی کل گروه یک فراداده (مثل * یا +) اعمال کرد.

برای مثال، برای پیدا کردن تمام خطوطی در یک فایل گزارش که حاوی کلمه‌ی "error" یا "warning" هستند، می‌توانیم بنویسیم:

$ grep -E "error|warning" system.log