Skip to content

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///

sed 's/development/production/' app.conf
port=8080
mode=production
debug=true

Bu natija faqat ekranga chiqadi, app.conf o'zgarmagan:

cat app.conf
port=8080
mode=development
debug=true

Sintaksis: s/andoza/almashtiruvchi/[flag]. / — ajratgich, boshqa belgi (masalan, #) ham ishlatilishi mumkin, ayniqsa andozada / bo'lsa qulay:

sed 's#/var/log#/srv/log#' <<< 'path=/var/log/app.log'

Har bir uchrashuvni almashtirish: g flagi

Sukut bo'yicha sed har satrda faqat birinchi uchrashuvni almashtiradi:

sed 's/ERROR/WARN/' requests.log
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:

sed 's/o/0/' <<< 'foo bar foo'
sed 's/o/0/g' <<< 'foo bar foo'
f0o bar foo
f00 bar f00

Faylni joyida o'zgartirish: -i

sed -i.bak 's/mode=development/mode=production/' app.conf
cat app.conf
port=8080
mode=production
debug=true

-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

grep -n 'mode=development' app.conf

Faqat kutilgan qator(lar) chiqqanini tasdiqlagach:

sed -i.bak 's/mode=development/mode=production/' app.conf
diff app.conf.bak app.conf

diff orqali aynan nima o'zgarganini ko'rish — sed -ini to'g'ridan-to'g'ri ishlatishdan xavfsizroq oraliq qadam.

Muayyan qatorni tanlash

sed -n '2p' requests.log
sed -n '2,3p' requests.log
sed '1d' requests.log
  • -n sukut bo'yicha chiqishni o'chiradi, faqat p (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:

sed -n '/ERROR/p' requests.log

Guruh va backreference

Qavs ichiga olingan qism keyin \1, \2 bilan qayta ishlatiladi:

sed -E 's/^([0-9-]+) ([0-9:]+) ([A-Z]+)/\3 \1T\2/' requests.log
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

awk '{ print $1, $3 }' requests.log
2026-07-24 INFO
2026-07-24 ERROR
2026-07-24 ERROR
2026-07-24 WARN

$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

awk '$3 == "ERROR" { print $1, $2, $4 }' requests.log
2026-07-24 10:00:02 api
2026-07-24 10:00:03 db

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
name=api
name=db

Yig'indi va hisoblash: BEGIN/END

awk '$3 == "ERROR" { count++ } END { print "ERROR soni:", count+0 }' requests.log
ERROR soni: 2

count+0count 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

awk '{ count[$3]++ } END { for (level in count) print level, count[level] }' requests.log
INFO 1
ERROR 2
WARN 1

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///da g flagini 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, total kabi awk o'zgaruvchisini +0 bilan songa aylantirmasdan chop etib, kutilmagan bo'sh natija olish;
  • sed va grepni bir xil vosita deb hisoblab, faqat qidirish kerak bo'lgan joyda sed -n '/pattern/p' yozish — grep shu vazifa uchun soddaroq.

Amaliy mashqlar

  1. app.conf faylida debug=true qiymatini debug=false ga sed -i.bak bilan almashtiring, so'ng diff bilan o'zgarishni tasdiqlang.
  2. requests.logdan faqat WARN va ERROR qatorlarini sed -n bilan, keyin xuddi shu natijani awk bilan chiqaring — ikkala yondashuvni solishtiring.
  3. awk bilan requests.logdagi har bir xizmat (api, db) uchun necha marta uchraganini sanang.
  4. sed -E bilan requests.logdagi sana va vaqtni bitta ustunga, T bilan 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.

Manbalar