Matnni qayta yozish: sed va awk
Fayl va matnni qidirish maqolasida grep satrni topadi, lekin uni o'zgartirmaydi. Log formatini almashtirish, konfiguratsiya faylidagi qiymatni skript orqali yangilash yoki ustunli hisobotdan raqam yig'ish kerak bo'lganda grep yetarli emas — bu ish sed va awkga tegishli.
Misollar Ubuntu Server LTSdagi GNU sed va GNU awk (gawk) uchun. Pipeline semantikasi maqolasidagi exit status va pipefail — prerequisite. Maqola oxirida siz sed bilan satrni xavfsiz almashtirishingiz, o'zgarishni faylga qaytarishdan oldin tekshirishingiz, awk bilan ustunli ma'lumotni filtrlab yig'ishingiz va ikkalasining qachon mos kelishini ajratishingiz kerak.
Laboratoriya ma'lumotlari
mkdir -p ~/lab/textproc
cd ~/lab/textproc
printf 'port=8080\nmode=development\ndebug=true\n' > app.conf
printf '%s\n' \
'2026-07-24 10:00:00 INFO api 12ms' \
'2026-07-24 10:00:02 ERROR api 340ms' \
'2026-07-24 10:00:03 ERROR db 890ms' \
'2026-07-24 10:00:04 WARN api 45ms' > requests.log
sed: satrlarni oqim sifatida qayta yozish
sed (stream editor) har bir satrni ketma-ket o'qiydi, unga buyruq qo'llaydi va natijani stdoutga chiqaradi. U faylni o'zgartirmaydi — buyruq alohida ko'rsatilmasa, asl fayl tegilmaydi.
Asosiy almashtirish: s///
Bu natija faqat ekranga chiqadi, app.conf o'zgarmagan:
Sintaksis: s/andoza/almashtiruvchi/[flag]. / — ajratgich, boshqa belgi (masalan, #) ham ishlatilishi mumkin, ayniqsa andozada / bo'lsa qulay:
Har bir uchrashuvni almashtirish: g flagi
Sukut bo'yicha sed har satrda faqat birinchi uchrashuvni almashtiradi:
2026-07-24 10:00:00 INFO api 12ms
2026-07-24 10:00:02 WARN api 340ms
2026-07-24 10:00:03 WARN db 890ms
2026-07-24 10:00:04 WARN api 45ms
Bu misolda har satrda bitta ERROR bo'lgani uchun farq ko'rinmaydi, lekin bir satrda bir nechta uchrashuv bo'lsa, g flagisiz faqat birinchisi almashadi:
Faylni joyida o'zgartirish: -i
-i.bak GNU sedda ikki narsa qiladi: asl faylni .bak kengaytmali nusxaga saqlaydi, so'ng asl faylni o'zgartiradi. Backup kengaytmasi berilmasa (-i yolg'iz), asl fayl orqaga qaytarilmaydigan holda tahrirlanadi.
Danger
sed -i — qaytarib bo'lmaydigan amal (backup kengaytmasi berilmasa). Production konfiguratsiya faylida ishlatishdan oldin: avval backup kengaytmasi bilan (-i.bak) sinang yoki backupsiz -i ishlatishdan oldin buyruqni -i siz, faqat ekranga chiqarib tekshiring. Noto'g'ri andoza kutilmagan qatorlarni ham o'zgartirishi mumkin — buni oldindan grep bilan qaysi satrlar mos kelishini ko'rib tasdiqlang.
O'zgarishdan oldin tekshirish odati
Faqat kutilgan qator(lar) chiqqanini tasdiqlagach:
diff orqali aynan nima o'zgarganini ko'rish — sed -ini to'g'ridan-to'g'ri ishlatishdan xavfsizroq oraliq qadam.
Muayyan qatorni tanlash
-nsukut bo'yicha chiqishni o'chiradi, faqatp(print) buyrug'i bilan ko'rsatilgan qatorlar chiqadi;2,3p— 2-dan 3-gacha qator oralig'i;1d— birinchi qatorni o'chirib, qolganini chiqaradi (fayl o'zgarmaydi, faqat oqim natijasi).
Andozaga mos qatorni tanlash raqam o'rniga regex bilan ham mumkin:
Guruh va backreference
Qavs ichiga olingan qism keyin \1, \2 bilan qayta ishlatiladi:
INFO 2026-07-24T10:00:00 api 12ms
ERROR 2026-07-24T10:00:02 api 340ms
ERROR 2026-07-24T10:00:03 db 890ms
WARN 2026-07-24T10:00:04 api 45ms
-E extended regexni yoqadi — qavs escape qilinmaydi (\(...\) o'rniga oddiy (...)). Bu misol sana, vaqt va darajani qayta joylashtirib, ISO 8601'ga yaqin format hosil qiladi.
awk: ustunli ma'lumot bilan ishlash
sed satrni butunligicha ko'radi; awk esa har satrni bo'shliq (yoki boshqa belgilangan ajratgich) bo'yicha ustunlarga ajratib, ular bilan hisoblash imkonini beradi.
Ustunni chiqarish
$1, $2, ... — bo'shliq bilan ajratilgan ustunlar, $0 esa butun satr. Sukut bo'yicha ajratgich — bir yoki bir nechta bo'shliq/tab.
Shart bilan filtrlash
grepdan farqi: awk faqat mos satrni topib qolmay, undan kerakli ustunni ajratib chiqaradi.
Maxsus ajratgich: -F
CSV yoki key=value formatidagi ma'lumot uchun:
printf 'name=api,status=up,latency=12\nname=db,status=down,latency=340\n' > services.csv
awk -F',' '{ print $1 }' services.csv
Yig'indi va hisoblash: BEGIN/END
count+0 — count hech qachon oshmagan holatda (ERROR topilmasa) uni bo'sh satr emas, 0 sifatida chiqarish uchun. awkda e'lon qilinmagan o'zgaruvchi sukut bo'yicha bo'sh/nol qiymatga ega.
BEGIN blogi ma'lumot o'qilishidan oldin, END esa hammasi o'qib bo'lingandan keyin bir marta ishga tushadi:
awk 'BEGIN { print "Tahlil boshlandi" }
$3 == "ERROR" { total += $4 + 0 }
END { print "Jami ERROR latency (ms):", total+0 }' requests.log
Bu misolda $4 (masalan, 340ms) to'g'ridan-to'g'ri songa aylanmaydi — awk matn boshidagi raqamni oladi, ms qismini e'tiborsiz qoldiradi, chunki arifmetik kontekstda satrni sonli qiymatga aylantiradi.
Ustunlar bo'yicha guruhlash
count[$3] — assotsiativ massiv (awkda barcha massiv shunday), kalit sifatida darajani ishlatadi. for (level in count) massiv kalitlari bo'yicha aylanadi; tartib kafolatlanmagan.
sed va awkni qachon tanlash
| Vazifa | Mos vosita | Sabab |
|---|---|---|
| Bitta satr ichida matnni almashtirish | sed |
Satrni butunligicha ko'radi, oddiy almashtirish uchun qulay |
| Konfiguratsiya faylidagi qiymatni yangilash | sed -i (ehtiyotkorlik bilan) |
Bitta qator, bitta almashtirish — ortiqcha emas |
| Ustunlardan ma'lum birini olish yoki hisoblash | awk |
Ustunlarni avtomatik ajratadi, arifmetika va massivni qo'llab-quvvatlaydi |
| Bir nechta shart bo'yicha yig'indi/statistika | awk |
BEGIN/END va assotsiativ massiv shu uchun mo'ljallangan |
| Faqat satrni topish, o'zgartirmasdan | grep |
Ikkalasi ham buni bajaradi, lekin grep soddaroq va tezroq |
Ikkalasi ham to'liq dasturlash tili darajasida murakkab bo'lishi mumkin; bu yerda ko'rilganlar — kundalik sysadmin vazifalari uchun asosiy qism.
Ko'p uchraydigan xatolar
sed -ini backup yoki oldindan tekshiruvsiz to'g'ridan-to'g'ri production faylga qo'llash;s///dagflagini unutib, faqat birinchi uchrashuv almashganini payqamaslik;awkda$3 == "ERROR"kabi shartni tirnoqsiz sonli solishtiruv deb yozish — matn solishtiruvda tirnoq muhim;awkdagi ustun raqamlarini faylning haqiqiy ajratgichini tekshirmasdan taxmin qilish (masalan, CSV uchun sukut bo'shliq ajratgichini ishlatish);count,totalkabiawko'zgaruvchisini+0bilan songa aylantirmasdan chop etib, kutilmagan bo'sh natija olish;sedvagrepni bir xil vosita deb hisoblab, faqat qidirish kerak bo'lgan joydased -n '/pattern/p'yozish —grepshu vazifa uchun soddaroq.
Amaliy mashqlar
app.conffaylidadebug=trueqiymatinidebug=falsegased -i.bakbilan almashtiring, so'ngdiffbilan o'zgarishni tasdiqlang.requests.logdan faqatWARNvaERRORqatorlarinised -nbilan, keyin xuddi shu natijaniawkbilan chiqaring — ikkala yondashuvni solishtiring.awkbilanrequests.logdagi har bir xizmat (api,db) uchun necha marta uchraganini sanang.sed -Ebilanrequests.logdagi sana va vaqtni bitta ustunga,Tbilan ajratib birlashtiring (yuqoridagi misolga o'xshab, lekin o'z andozangiz bilan).
Tekshiruv mezoni: har bir natija uchun qaysi vosita (sed yoki awk) tanlanganini va nega aynan shu vosita mos kelganini izohlay olishingiz kerak.
Xulosa
sed oqimni satr-satr o'qib, andozaga mos qismini almashtiradi yoki tanlaydi — konfiguratsiya faylidagi bitta qiymatni yangilash kabi vazifalar uchun qulay. awk esa har satrni ustunlarga ajratib, shart, hisoblash va guruhlashni qo'llab-quvvatlaydi — hisobot va statistika uchun mos. sed -i qaytarib bo'lmaydigan o'zgarish kiritadi, shuning uchun backup yoki oldindan tekshiruv doimiy odat bo'lishi kerak. Keyingi arxivlash va siqish maqolasi shu tahlil natijalarini tar va siqish vositalari bilan saqlash va uzatishni ko'rsatadi.