Pipe، Redirection، جست‌وجو و پردازش متن

جریان‌های استاندارد

هر فرایند در Linux سه جریان متنی استاندارد دارد:

  • ورودی استاندارد (stdin) — ورودی دستور؛ شماره‌ی توصیف‌گر فایل آن 0 است
  • خروجی استاندارد (stdout) — خروجی عادی دستور؛ شماره‌ی آن 1 است
  • خطای استاندارد (stderr) — پیام خطا؛ شماره‌ی آن 2 است

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

1date > today.txt
2date >> today.txt
3sort < names.txt
4find /root -type f 2> errors.txt
5command > output.txt 2>&1
  • > فایل را ایجاد یا جایگزین می‌کند؛ در نتیجه پیش از اجرا مطمئن شوید فایل مهمی را بازنویسی نمی‌کنید.
  • >> خروجی را به انتهای فایل اضافه می‌کند.
  • < محتویات فایل را ورودی دستور می‌کند.
  • 2> فقط خطاها را به فایل می‌فرستد.
  • 2>&1 خطا را به همان مقصدی می‌فرستد که خروجی عادی رفته است.

Pipe

Pipe با |، stdout یک دستور را به stdin دستور بعدی وصل می‌کند. این مدل کوچک و ترکیبی، بخش مهمی از فلسفهٔ Unix است: هر ابزار یک کار محدود را خوب انجام می‌دهد.

1ps aux | grep '[s]shd'
2journalctl -u ssh --no-pager | tail -n 20

در مثال اول، نوشتن [s]shd باعث می‌شود خود فرایند grep در نتیجه نمایش داده نشود (چرا؟). در بسیاری از موقعیت‌ها pgrep sshd ابزار مناسب‌تر و خواناتری است.

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

1df -h | tee disk-usage.txt

جست‌وجوی متن با grep

grep خط‌های منطبق با یک الگو را چاپ می‌کند. چند گزینهٔ پرکاربرد:

1grep -n "ERROR" app.log
2grep -i "warning" app.log
3grep -v '^#' config.conf
4grep -E 'ERROR|FATAL' app.log
5grep -RIn --include='*.conf' 'listen' /etc
  • -n شمارهٔ خط و -i جست‌وجوی بدون حساسیت به بزرگی/کوچکی حروف را اضافه می‌کند.
  • -v خط‌های غیرمنطبق را انتخاب می‌کند؛ نمونهٔ بالا توضیحات را حذف می‌کند.
  • -E از Extended Regular Expression استفاده می‌کند.
  • -R در دایرکتوری‌ها بازگشتی جست‌وجو می‌کند و -I فایل‌های باینری را نادیده می‌گیرد.

استفاده از single quote برای الگوهای regex امن‌تر است؛ به این شکل shell نویسه‌هایی مانند * و ? را پیش از رسیدن به grep تغییر نمی‌دهد.

پیدا کردن فایل‌ها با find

find فایل‌ها را بر اساس نام، نوع، زمان، اندازه یا مالک پیدا می‌کند. نقطهٔ آغاز جست‌وجو را تا حد ممکن محدود انتخاب کنید:

1find ~/project -type f -name '*.log'
2find /var/log -type f -mtime -7
3find /tmp -type f -size +100M
4find . -type d -name node_modules -prune
  • -type f فایل و -type d دایرکتوری را انتخاب می‌کند.
  • -mtime -7 به فایل‌های تغییرکرده در هفت روز اخیر اشاره دارد.
  • -prune در مثال آخر مانع ورود به دایرکتوری‌های node_modules می‌شود.

اگر خروجی find به دستور دیگری می‌رود، با نام‌های دارای فاصله درست رفتار کنید. ترکیب -print0 و xargs -0 جداکنندهٔ NUL به کار می‌برد و برای همهٔ نام‌های فایل امن است:

1find . -type f -name '*.log' -print0 | xargs -0 grep -nH 'ERROR'

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

1find ~/linux-lab -type f -name '*.tmp' -print

تبدیل و خلاصه‌سازی متن

ابزارهای کوچک زیر را کنار هم قرار دهید تا پاسخ یک سؤال عملی را بسازید:

1cut -d: -f1 /etc/passwd
2sort access.log | uniq -c | sort -nr
3tr '[:lower:]' '[:upper:]' < input.txt
4sed -n '1,10p' app.log
5awk '{print $1, $7}' access.log
  • cut ستون‌ها را با جداکنندهٔ مشخص استخراج می‌کند.
  • sort مرتب و uniq -c تعداد رخدادهای متوالی را می‌شمارد؛ پس پیش از آن معمولاً sort لازم است.
  • tr نویسه‌ها را تبدیل (ترجمه) می‌کند.
  • sed برای انتخاب یا جایگزینی خط‌ها و awk برای کار با ستون‌ها مناسب‌اند.

این pipeline تعداد IPهای پرتکرار در یک فایل لاگ دسترسی را نشان می‌دهد:

1awk '{print $1}' access.log | sort | uniq -c | sort -nr | head

pipelineهای طولانی را مرحله‌به‌مرحله بسازید. ابتدا خروجی هر دستور را بررسی کنید، سپس آن را به دستور بعدی وصل کنید. این روش عیب‌یابی را ساده‌تر می‌کند.

منابع یادگیری

مستندات و مقالات

ویدیو