توی این درس یاد میگیری دو ابزار پردازش متن: sed (stream editor) که متن را جایگزین یا حذف میکند (sed 's/old/new/g') و با sed -i فایل را «درجا» ویرایش میکند، و awk که متن را به ستونها (فیلدها) میشکند و محاسبه میکند (awk '{print $1}'، awk -F:). شرط و جمع زدن در awk، بخشهای BEGIN و END و شمارش با آرایه را میبینی. تمرین: از /etc/passwd نام کاربرها و shell شان را استخراج میکنی.
مسئله: ویرایش صدها فایل بدون باز کردن آنها
Section titled “مسئله: ویرایش صدها فایل بدون باز کردن آنها”باید در ۲۰۰ فایل تنظیمات، پورت 80 را به 8080 تغییر بدهی. یا از خروجی یک دستور فقط ستون سوم و پنجم را بخواهی، یا مجموع یک ستون را حساب کنی. با ویرایشگر و ماشینحساب ساعتها طول میکشد؛ با sed و awk چند ثانیه. این دو ابزار مثل «جستجو و جایگزینی» و «اکسل خط فرمان» هستند.
تشبیه: قیچی و ماشینحساب
Section titled “تشبیه: قیچی و ماشینحساب”sed مثل «جستجو و جایگزینی» ویرایشگر است ولی روی جریان متن و بدون باز کردن: هر خط میآید، تغییر میکند و میرود. awk مثل یک جدولخوان است: هر خط را به ستونها میشکند و میتوانی روی ستونها شرط بگذاری و جمع بزنی. اولی «ویرایش»، دومی «تحلیل و گزارش».
مثالهای عملی
Section titled “مثالهای عملی”دادههای تمرین: یک فایل تنظیمات، یک CSV فروش و یک لاگ ساده:
cat > app.conf <<'LXEOF'# تنظیمات برنامهname=webport=80debug=trueserver=old-server.example.combackup_server=old-server.example.comLXEOFcat > sales.csv <<'LXEOF'product,qty,priceapple,10,2banana,5,3apple,4,2cherry,20,1banana,2,3LXEOFawk 'BEGIN{for(i=1;i<=20;i++) print "2026-10-03 12:" (i<10?"0":"") i ":00", (i%4==0?"ERROR":"INFO"), "task", i, "done in", i*10 "ms"}' > run.logecho "ساخته شد"; lsساخته شدapp.confrun.logsales.csvمثال ۱: جایگزینی با sed، s/قدیم/جدید/
Section titled “مثال ۱: جایگزینی با sed، s/قدیم/جدید/”دستور s (substitute): s/الگو/جایگزین/. بهطور پیشفرض اولین مورد هر خط را عوض میکند و فایل اصلی را تغییر نمیدهد (فقط نتیجه را چاپ میکند):
echo "--- جایگزینی ساده:"echo "hello world, hello sed" | sed 's/hello/bye/'echo "--- با g (همهی موارد هر خط):"echo "hello world, hello sed" | sed 's/hello/bye/g'echo "--- روی فایل:"sed 's/80/8080/' app.conf | grep portecho "--- فایل اصلی هنوز دستنخورده:"grep port app.conf--- جایگزینی ساده:bye world, hello sed--- با g (همهی موارد هر خط):bye world, bye sed--- روی فایل:port=8080--- فایل اصلی هنوز دستنخورده:port=80g یعنی global (همهی تطبیقها). و چون sed خروجی را چاپ میکند، فایل اصلی تغییر نکرد؛ برای تغییر واقعی باید -i بدهی (مثال ۳).
مثال ۲: جداکنندهی دیگر، &، و regex در sed
Section titled “مثال ۲: جداکنندهی دیگر، &، و regex در sed”اگر الگو شامل / است، هر کاراکتر دیگری را بهجای جداکننده بگذار (|، #، ,):
echo "/usr/local/bin" | sed 's/\/usr\/local/\/opt/'echo "--- خواناتر با |:"echo "/usr/local/bin" | sed 's|/usr/local|/opt|'echo "--- & یعنی خود متن منطبق:"echo "port 80 and 443" | sed 's/[0-9][0-9]*/[&]/g'echo "--- بیحساس به حروف (I) و regex توسعهیافته (-E با گروه \\1):"echo "Hello HELLO hello" | sed 's/hello/X/Ig'echo "ali:1001" | sed -E 's/([a-z]+):([0-9]+)/\2 → \1/'/opt/bin--- خواناتر با |:/opt/bin--- & یعنی خود متن منطبق:port [80] and [443]--- بیحساس به حروف (I) و regex توسعهیافته (-E با گروه \1):X X X1001 → aliدر بخش جایگزین، & کل متن منطبق است و \1 \2 گروههای داخل پرانتز (با -E). این برای جابهجا کردن بخشهای یک متن عالی است.
sed 's/a/b/' چه چیزی را عوض میکند؟
و بدون -i فایل اصلی دستنخورده میماند؛ فقط خروجی تغییر میکند.
مثال ۳: ویرایش درجا، sed -i
Section titled “مثال ۳: ویرایش درجا، sed -i”با -i تغییر در خود فایل اعمال میشود. همیشه قبلش بدون -i امتحان کن، و بهتر است با -i.bak یک نسخهی پشتیبان هم بگیری:
cp app.conf app-test.confecho "--- پیشنمایش (بدون -i):"sed 's/^port=.*/port=9090/' app-test.conf | grep portecho "--- اعمال با بکاپ (-i.bak):"sed -i.bak 's/^port=.*/port=9090/' app-test.confgrep port app-test.confecho "--- بکاپ اصلی:"grep port app-test.conf.bakls app-test.conf*--- پیشنمایش (بدون -i):port=9090--- اعمال با بکاپ (-i.bak):port=9090--- بکاپ اصلی:port=80app-test.confapp-test.conf.bak^port=.* یعنی «خطی که با port= شروع میشود، با هر چیزی بعدش»؛ کل خط با port=9090 جایگزین شد. فایل app-test.conf.bak نسخهی قبل از تغییر است. (روی macOS sed -i بدون پسوند کار نمیکند و -i '' لازم است؛ -i.bak در هر دو کار میکند.)
مثال ۴: آدرسدهی خطها: حذف و چاپ انتخابی
Section titled “مثال ۴: آدرسدهی خطها: حذف و چاپ انتخابی”قبل از دستور میتوانی کدام خطها را مشخص کنی: شمارهی خط (3)، بازه (2,4)، آخرین خط ($)، یا یک regex (/الگو/):
echo "--- فقط خطهای 2 تا 3 (-n + p):"sed -n '2,3p' app.confecho "--- حذف خطهای توضیح (که با # شروع میشوند):"sed '/^#/d' app.confecho "--- حذف خط اول و آخر:"sed '1d;$d' app.conf | head -3echo "--- فقط خطهای دارای server (مثل grep):"sed -n '/server/p' app.confecho "--- جایگزینی فقط در خطهای مشخص (خطهایی که server دارند):"sed '/^backup/s/old-server/new-server/' app.conf | grep server--- فقط خطهای 2 تا 3 (-n + p):name=webport=80--- حذف خطهای توضیح (که با # شروع میشوند):name=webport=80debug=trueserver=old-server.example.combackup_server=old-server.example.com--- حذف خط اول و آخر:name=webport=80debug=true--- فقط خطهای دارای server (مثل grep):server=old-server.example.combackup_server=old-server.example.com--- جایگزینی فقط در خطهای مشخص (خطهایی که server دارند):server=old-server.example.combackup_server=new-server.example.com-n چاپ خودکار را خاموش میکند و p یعنی «همین خط را چاپ کن» (ترکیب -n و p = «فقط خطهای انتخابشده»). d یعنی حذف. چند دستور را با ; یا -e پشت هم مینویسی. آدرس قبل از s هم میآید تا جایگزینی فقط روی آن خطها انجام شود.
مثال ۵: درج و تغییر خط، i، a، c
Section titled “مثال ۵: درج و تغییر خط، i، a، c”echo "--- افزودن بعد از خط 2 (a):"sed '2a\# خط اضافهشده' app.conf | head -4echo "--- درج قبل از خطی که port دارد (i):"sed '/^port=/i\# پورت زیر را عوض نکن' app.conf | sed -n '3,4p'echo "--- تعویض کل خط debug (c):"sed 's/^debug=.*/debug=false/' app.conf | grep debugecho "--- غیرفعال کردن یک خط با # (توضیحشدن):"sed '/^debug=/s/^/#/' app.conf | grep debug--- افزودن بعد از خط 2 (a):# تنظیمات برنامهname=web# خط اضافهشدهport=80--- درج قبل از خطی که port دارد (i):# پورت زیر را عوض نکنport=80--- تعویض کل خط debug (c):debug=false--- غیرفعال کردن یک خط با # (توضیحشدن):#debug=truea\ متن را بعد از خط، i\ قبل از آن و c\ بهجای آن میگذارد. و s/^/#/ ابتدای خط یک # اضافه میکند (غیرفعال کردن یک تنظیم)، که رایجترین ویرایش تنظیمات است.
مثال ۶: awk، فیلدها
Section titled “مثال ۶: awk، فیلدها”awk هر خط را با فاصله به فیلد میشکند: $1 فیلد اول، $2 دوم، $NF آخرین فیلد، $0 کل خط، NF تعداد فیلدها، NR شمارهی خط:
echo "ali 25 tehran" | awk '{print $1}'echo "ali 25 tehran" | awk '{print $3, $1}'echo "ali 25 tehran" | awk '{print "فیلدها:", NF, "آخرین:", $NF}'echo "--- run.log: ستونهای 3 و 4 از خطهای 1 تا 3:"head -3 run.log | awk '{print NR ": " $3, $4}'alitehran aliفیلدها: 3 آخرین: tehran--- run.log: ستونهای 3 و 4 از خطهای 1 تا 3:1: INFO task2: INFO task3: INFO taskساختار کلی awk: awk 'شرط { عمل }'. اگر شرط نباشد برای همهی خطها؛ اگر عمل نباشد، خط چاپ میشود. برخلاف cut، awk چند فاصلهی پشت هم را یک جداکننده میبیند، که برای خروجی دستورهایی مثل ps و df عالی است:
df -h / | awk 'NR==2 {print "فضای آزاد:", $4, "از", $2, "(پر:", $5 ")"}'ls -l /etc/hostname /etc/os-release | awk '{print $5, $9}'فضای آزاد: 408G از 453G (پر: 6%)3 /etc/hostname21 /etc/os-releaseمثال ۷: جداکنندهی دلخواه، -F، و تمرین اصلی
Section titled “مثال ۷: جداکنندهی دلخواه، -F، و تمرین اصلی”-F جداکنندهی فیلد را عوض میکند. /etc/passwd با : جدا شده است:
echo "--- نام کاربر و shell او (ستونهای 1 و 7):"awk -F: '{print $1, $7}' /etc/passwd | head -4echo "--- فقط کاربرهایی که shell واقعی دارند:"awk -F: '$7 ~ /bash$/ {print $1 " → " $7}' /etc/passwdecho "--- جداکنندهی خروجی (OFS) و CSV:"awk -F, 'NR>1 {print $1, $2}' OFS=" | " sales.csv | head -3--- نام کاربر و shell او (ستونهای 1 و 7):root /bin/bashdaemon /usr/sbin/nologinbin /usr/sbin/nologinsys /usr/sbin/nologin--- فقط کاربرهایی که shell واقعی دارند:root → /bin/bashubuntu → /bin/bashali → /bin/bash--- جداکنندهی خروجی (OFS) و CSV:apple | 10banana | 5apple | 4این همان تمرین درس است: awk -F: '{print $1, $7}' /etc/passwd اسم کاربرها و shellشان را میدهد. ~ یعنی «با این regex جور است»؛ و NR>1 سطر اول (هدر) را رد میکند.
مثال ۸: شرط و جمع، BEGIN و END
Section titled “مثال ۸: شرط و جمع، BEGIN و END”بخش BEGIN { } قبل از خواندن ورودی و END { } بعد از آن اجرا میشود. با اینها جمع و میانگین میگیری:
echo "--- جمع تعداد (ستون 2) بدون هدر:"awk -F, 'NR>1 {s += $2} END {print "جمع qty:", s}' sales.csvecho "--- مبلغ کل (qty × price):"awk -F, 'NR>1 {total += $2 * $3} END {print "مجموع فروش:", total}' sales.csvecho "--- فقط ردیفهایی که qty بیشتر از 4 است:"awk -F, 'NR>1 && $2 > 4 {print $1, $2}' sales.csvecho "--- میانگین و تعداد:"awk -F, 'NR>1 {n++; s += $2} END {printf "تعداد=%d میانگین qty=%.2f\n", n, s/n}' sales.csvecho "--- یک عنوان با BEGIN:"awk -F, 'BEGIN {print "گزارش فروش"; print "----------"} NR>1 {print $1 ": " $2*$3}' sales.csv | head -4--- جمع تعداد (ستون 2) بدون هدر:جمع qty: 41--- مبلغ کل (qty × price):مجموع فروش: 69--- فقط ردیفهایی که qty بیشتر از 4 است:apple 10banana 5cherry 20--- میانگین و تعداد:تعداد=5 میانگین qty=8.20--- یک عنوان با BEGIN:گزارش فروش----------apple: 20banana: 15متغیرهای awk نیاز به تعریف ندارند و مقدار اولیهشان صفر است. printf مثل زبان C قالببندی میکند (%d عدد صحیح، %.2f دو رقم اعشار، %s رشته).
مثال ۹: شمارش با آرایه، فروش هر محصول
Section titled “مثال ۹: شمارش با آرایه، فروش هر محصول”آرایهها در awk انجمنی (associative) هستند: کلیدشان هر متنی میتواند باشد. این الگوی «گروهبندی و جمع» است (مثل GROUP BY در SQL):
echo "--- مجموع فروش هر محصول:"awk -F, 'NR>1 {sum[$1] += $2 * $3} END {for (p in sum) print p, sum[p]}' sales.csv | sortecho "--- تعداد دفعات تکرار هر نوع خط در run.log (INFO/ERROR):"awk '{count[$3]++} END {for (k in count) print count[k], k}' run.log | sort -rnecho "--- بیشترین مدت (ms) در خطهای ERROR:"awk '$3 == "ERROR" {gsub("ms", "", $NF); if ($NF + 0 > max) max = $NF + 0} END {print max "ms"}' run.log--- مجموع فروش هر محصول:apple 28banana 21cherry 20--- تعداد دفعات تکرار هر نوع خط در run.log (INFO/ERROR):15 INFO5 ERROR--- بیشترین مدت (ms) در خطهای ERROR:200mscount[$3]++ برای هر مقدار ستون ۳ (نوع پیام: INFO یا ERROR) یک شمارنده میسازد و یکی بالا میبرد؛ for (k in count) روی کلیدها میچرخد (ترتیب نامشخص است، پس sort بعدش). gsub جایگزینی regex در خود awk است. این تحلیل «پرتکرارترینها» را بدون sort | uniq -c هم میدهد (درس pipe).
مثال ۱۰: ترکیب sed و awk در یک pipeline
Section titled “مثال ۱۰: ترکیب sed و awk در یک pipeline”echo "--- ۱) sed: تمیز کردن، awk: ستونها:"printf 'name: ali , age: 25\nname: sara , age: 31\n' | sed 's/[ ]*,[ ]*/,/; s/:[ ]*/:/g' | awk -F'[:,]' '{print $2, $4}'echo "--- ۲) تغییر در همهی فایلهای یک پوشه (پیشنمایش با sed -n):"mkdir -p confs && printf 'host=old\nport=80\n' > confs/a.conf && printf 'host=old\n' > confs/b.confsed -n 's/host=old/host=new/p' confs/*.confecho "--- ۳) اعمال با -i:"sed -i 's/host=old/host=new/' confs/*.confgrep -H host confs/*.conf--- ۱) sed: تمیز کردن، awk: ستونها:ali 25sara 31--- ۲) تغییر در همهی فایلهای یک پوشه (پیشنمایش با sed -n):host=newhost=new--- ۳) اعمال با -i:confs/a.conf:host=newconfs/b.conf:host=newالگوی رایج کار با فایلهای تنظیمات: ۱) با -n ... p ببین چه چیزی تغییر میکند، ۲) بعد با -i اعمال کن (ترجیحاً با .bak). و اگر منطق ستونی/محاسباتی داری، awk؛ اگر جایگزینی ساده، sed.
پشت پرده: چرخهی خطبهخط
Section titled “پشت پرده: چرخهی خطبهخط”هر دو ابزار الگوی ثابتی دارند: یک خط را بخوان ← عملها را اجرا کن ← خروجی بده ← خط بعدی. در sed این چرخه «pattern space» نام دارد: خط در یک بافر قرار میگیرد، دستورها (s، d، p) بهترتیب روی بافر اجرا میشوند و در پایان (مگر -n) بافر چاپ میشود. در awk برای هر خط، متغیرهای $0 و $1... ساخته میشوند و بلوکهایی که شرطشان درست است اجرا میشوند.
دو نکتهی مهم: ۱) هیچکدام کل فایل را در حافظه نمیریزند، پس برای فایلهای چندگیگابایتی هم کار میکنند؛ ۲) sed -i در واقع یک فایل موقت میسازد، نتیجه را در آن مینویسد و بعد جایگزین فایل اصلی میکند (یک inode جدید؛ لینکهای سخت و دسترسیها ممکن است تحت تأثیر قرار بگیرند؛ --follow-symlinks برای لینکهای نمادین). و برای تغییرات بزرگ همیشه بکاپ.
انتخاب ابزار: cut برای برش سادهی ستون با جداکنندهی ثابت، sed برای جایگزینی و حذف/درج خط، awk برای ستونهای متغیر، شرط، محاسبه و گزارش. وقتی منطق پیچیده شد، یک اسکریپت bash یا پایتون بنویس.
جدولهای مرجع
Section titled “جدولهای مرجع”| دستور sed | معنی |
|---|---|
s/a/b/ |
اولین a هر خط را به b |
s/a/b/g |
همهی a ها |
s/a/b/I |
بیحساس به حروف |
-n '2,4p' |
فقط خطهای ۲ تا ۴ |
'/الگو/d' |
حذف خطهای منطبق |
'$d' / '1d' |
حذف آخرین / اولین خط |
'2a\متن' / '2i\متن' |
افزودن بعد / قبل از خط ۲ |
-E |
regex توسعهیافته (\1 برای گروه) |
-i / -i.bak |
ویرایش درجا / با بکاپ |
-e 'cmd1' -e 'cmd2' |
چند دستور |
| در awk | معنی |
|---|---|
$1 $2 ... $NF |
فیلدها ($NF آخرین) |
$0 |
کل خط |
NR / NF |
شمارهی خط / تعداد فیلد |
-F: |
جداکنندهی فیلد (:) |
BEGIN {...} / END {...} |
قبل از شروع / بعد از پایان |
$3 > 100 {print} |
شرط روی فیلد |
/regex/ {print} |
شرط regex روی خط |
$1 ~ /x/ |
فیلد با regex جور است |
sum += $2 |
جمع |
count[$1]++ |
آرایهی شمارنده |
printf "%d %.2f %s\n" |
چاپ قالببندیشده |
اشتباهات رایج
Section titled “اشتباهات رایج”۱) فراموش کردن g
Section titled “۱) فراموش کردن g”echo "a-a-a" | sed 's/a/X/'echo "a-a-a" | sed 's/a/X/g'X-a-aX-X-Xبدون g فقط اولین مورد هر خط عوض میشود. راهحل: g برای همه.
۲) sed -i بدون پیشنمایش و بکاپ
Section titled “۲) sed -i بدون پیشنمایش و بکاپ”echo "version=1.0" > ver.txtsed -i 's/1.0/2.0/' ver.txtcat ver.txtecho "--- ولی نقطه = هر کاراکتر! این هم عوض میشود:"echo "version=1x0" > ver2.txtsed -i 's/1.0/2.0/' ver2.txtcat ver2.txtversion=2.0--- ولی نقطه = هر کاراکتر! این هم عوض میشود:version=2.01.0 در regex با 1x0 هم جور است (نقطه = هر کاراکتر). راهحل: 1\.0، و قبل از -i پیشنمایش و بکاپ (-i.bak).
۳) quote اشتباه با متغیر shell
Section titled “۳) quote اشتباه با متغیر shell”name="ali"echo "hello NAME" | sed 's/NAME/$name/'echo "--- با دابلquote (shell متغیر را جایگزین میکند):"echo "hello NAME" | sed "s/NAME/$name/"hello $name--- با دابلquote (shell متغیر را جایگزین میکند):hello aliداخل '...' متغیر باز نمیشود. راهحل: دابلquote برای متغیر (و مواظب / یا & در مقدار باش).
۴) استفاده از awk با جداکنندهی اشتباه
Section titled “۴) استفاده از awk با جداکنندهی اشتباه”echo "a,b,c" | awk '{print $2}'echo "--- با -F,:"echo "a,b,c" | awk -F, '{print $2}'--- با -F,:bبدون -F, کل خط یک فیلد است و $2 خالی. راهحل: -F, (یا -F'[,;]' برای چند جداکننده).
۵) فراموش کردن حذف سطر هدر در محاسبه
Section titled “۵) فراموش کردن حذف سطر هدر در محاسبه”echo "--- بدون NR>1 (سطر هدر هم شمرده میشود):"awk -F, '{n++; s += $2} END {printf "تعداد=%d جمع=%d میانگین=%.2f\n", n, s, s/n}' sales.csvecho "--- با NR>1:"awk -F, 'NR>1 {n++; s += $2} END {printf "تعداد=%d جمع=%d میانگین=%.2f\n", n, s, s/n}' sales.csv--- بدون NR>1 (سطر هدر هم شمرده میشود):تعداد=6 جمع=41 میانگین=6.83--- با NR>1:تعداد=5 جمع=41 میانگین=8.20هدر (qty) بهعنوان عدد صفر جمع میشود و یک ردیف اضافی در شمارش میآید؛ جمع یکی است ولی تعداد و میانگین غلط میشود (۶ بهجای ۵ ردیف و میانگین ۶٫۸۳ بهجای ۸٫۲۰). راهحل: NR>1.
در app.conf همهی old-server ها را به new-server تغییر بده (فقط چاپ کن، فایل را عوض نکن) و بگو چند خط عوض شد.
دیدن جواب
cat > app.conf <<'LXEOF'server=old-server.example.combackup_server=old-server.example.comport=80LXEOFsed 's/old-server/new-server/g' app.confecho "تعداد خطهای عوضشده: $(sed -n 's/old-server/new-server/p' app.conf | wc -l)"server=new-server.example.combackup_server=new-server.example.comport=80تعداد خطهای عوضشده: 2تمرین اصلی: از /etc/passwd اسم کاربرها و shell شان را استخراج کن. با awk -F: ستونهای ۱ و ۷ را چاپ کن، بعد فقط کاربرهایی که shell شان nologin نیست را نشان بده و تعدادشان را بنویس.
دیدن جواب
echo "--- ۵ خط اول:"awk -F: '{print $1 "\t" $7}' /etc/passwd | head -5echo "--- کاربرهای با shell غیر nologin:"awk -F: '$7 !~ /nologin$/ {print $1, $7}' /etc/passwdecho "تعدادشان: $(awk -F: '$7 !~ /nologin$/' /etc/passwd | wc -l)"--- ۵ خط اول:root /bin/bashdaemon /usr/sbin/nologinbin /usr/sbin/nologinsys /usr/sbin/nologinsync /bin/sync--- کاربرهای با shell غیر nologin:root /bin/bashsync /bin/syncubuntu /bin/bashali /bin/bashتعدادشان: 4!~ یعنی «با این regex جور نیست».
یک گزارش بساز: در sales.csv برای هر محصول مجموع تعداد و مجموع مبلغ (qty×price) را چاپ کن، مرتب بر اساس مبلغ نزولی، و در انتها یک خط «جمع کل». (راهنما: آرایهی awk + sort -k3 -nr، یا همهی کار در awk.)
دیدن جواب
cat > sales.csv <<'LXEOF'product,qty,priceapple,10,2banana,5,3apple,4,2cherry,20,1banana,2,3LXEOFawk -F, 'NR>1 {q[$1] += $2; m[$1] += $2 * $3; all += $2 * $3} END {for (p in q) printf "%s %d %d\n", p, q[p], m[p]; printf "جمعکل - - %d\n", all}' sales.csv | sort -k3 -nrapple 14 28banana 7 21cherry 20 20جمعکل - - 69آزمونک
Section titled “آزمونک”sed 's/cat/dog/g' چه میکند؟
g یعنی global؛ برای تغییر فایل -i لازم است.
برای ویرایش درجا با بکاپ؟
فایل قبلی با پسوند .bak میماند.
awk -F: '{print $1}' /etc/passwd چه چاپ میکند؟
-F جداکنندهی فیلد را عوض میکند.
$NF در awk چیست؟
NF تعداد فیلدهاست؛ $NF آخرین فیلد.
بخش END { } در awk کی اجرا میشود؟
BEGIN قبل و END بعد.
sed -n "2,4p" چه میکند؟
-n چاپ خودکار را خاموش و p همان خطها را چاپ میکند.
جمعبندی
Section titled “جمعبندی”- sed:
s/قدیم/جدید/(اولین مورد) وs/.../.../g(همه)؛ آدرس خط (2,4،/regex/،$) باd(حذف)،p(چاپ با-n)،a\i\c\؛-iویرایش درجا (با-i.bakبکاپ). - awk: فیلدها
$1 $2 ... $NF،-F:جداکننده، شرط ($3 > 100،/regex/،NR>1)،BEGIN/END، جمع (s += $2) و آرایهی انجمنی (count[$1]++). - اول بدون
-iامتحان کن؛ در regex نقطه = هر کاراکتر (1\.0)؛ متغیر shell نیاز به دابلquote دارد. cutساده،sedویرایش،awkتحلیل ستونی و گزارش؛ برای منطق پیچیده، اسکریپت.- هر دو خطبهخط کار میکنند و برای فایلهای بزرگ مناسباند.
| دستور | کاری که میکند |
|---|---|
sed 's/old/new/g' file | جایگزینی همهی موارد (چاپ نتیجه) |
sed -i.bak 's/old/new/g' file | ویرایش درجا با بکاپ |
sed -n '2,4p' file | فقط خطهای ۲ تا ۴ |
sed '/^#/d' file | حذف خطهای توضیح |
sed 's|/a|/b|' file | جداکنندهی دیگر برای مسیرها |
awk '{print $1, $NF}' file | ستون اول و آخر |
awk -F: '{print $1, $7}' /etc/passwd | ستونها با جداکنندهی : |
awk '$3 > 100 {print $1}' file | شرط روی ستون |
awk '{s+=$1} END{print s}' file | جمع یک ستون |
awk '{c[$1]++} END{for(k in c) print c[k], k}' file | شمارش هر مقدار |
awk 'NR>1' file | رد کردن سطر هدر |