Matnni qayta yozish: sed va awk
Fayl va matn qidirish maqolasida ko'rilgan grep qatorni topadi, lekin uni o'zgartirmaydi. Log formatini qayta tuzish, skript orqali konfiguratsiyadagi qiymatni yangilash yoki hisobotdagi sonlar ustunini qo'shib chiqish kerak bo'lsa, bitta grep yetmaydi. Bu sed va awk ning vazifasi.
Misollar Ubuntu Server LTS’dagi GNU sed va GNU awk (gawk) uchun yozilgan. Sizga Oqimlar, pipe va yo'naltirish maqolasidagi chiqish holati va pipefail tushunchalari tanish bo'lishi kerak. Quyida sed bilan qatorni xavfsiz qayta yozishni, o'zgarishni faylga tegishidan oldin tekshirishni, awk bilan ustunli ma’lumotlarni umumlashtirishni va vazifaga qaysi vosita mosligini aniqlashni ko'rib chiqamiz.
Laboratoriyani tayyorlash
mkdir -p ~/lab/textproc
cd ~/lab/textproc
printf 'listen_port=8080\nenv=staging\ndebug=true\n' > app.conf
printf '%s\n' \
'2026-07-29 10:00:00 INFO orders-api 12ms' \
'2026-07-29 10:00:02 ERROR orders-api 340ms' \
'2026-07-29 10:00:03 ERROR billing-db 890ms' \
'2026-07-29 10:00:04 WARN orders-api 45ms' > requests.log
sed: oqimni qatorma-qator qayta yozish
sed (stream editor — oqim muharriri) qatorlarni birin-ketin o'qiydi, har biriga buyruq qo'llaydi va natijani standart chiqishga yozadi. Agar buni alohida aytmasangiz, u asl faylga tegmaydi: faylni joyida o'zgartirish bayrog'i bo'lmasa, manba fayl o'zgarishsiz qoladi.
Oddiy almashtirish: s///
Bu natija faqat ekranga chiqdi, app.conf ning o'zi esa o'zgarmadi:
Sintaksis: s/pattern/replacement/[flags], ya’ni s/andoza/almashtiriladigan_matn/[bayroqlar]. / — ajratuvchi, lekin uning o'rniga istalgan boshqa belgini ishlatish mumkin. Andozaning o'zida / bo'lsa, # qulay:
Hamma mosliklarni almashtirish: g bayrog'i
Sukut bo'yicha sed har bir qatordagi faqat birinchi moslikni almashtiradi:
2026-07-29 10:00:00 INFO orders-api 12ms
2026-07-29 10:00:02 WARN orders-api 340ms
2026-07-29 10:00:03 WARN billing-db 890ms
2026-07-29 10:00:04 WARN orders-api 45ms
Bu faylning har bir qatorida bittadan moslik bor, shuning uchun farq ko'rinmaydi. Qatorda bir nechta moslik bo'lsa, g qo'shmaguningizcha faqat birinchisi o'zgaradi:
Faylni joyida tahrirlash: -i
GNU sed da -i.bak ikki ishni bajaradi: asl faylni .bak nusxa sifatida saqlaydi, so'ng asl faylni joyida tahrirlaydi. Zaxira qo'shimchasi bo'lmasa (yalang'och -i), asl fayl qaytarib bo'lmaydigan tarzda o'zgaradi.
Danger
Zaxira qo'shimchasisiz sed -i ni ortga qaytarib bo'lmaydi. Production konfiguratsiya fayliga tegishdan oldin yoki zaxira qo'shimchasini bering (-i.bak), yoki avval xuddi shu almashtirishni -i siz ishga tushirib, u faqat kutilgan qatorlarga ta’sir qilishini tasdiqlang. Kutilganidan kengroq andoza siz umuman tegmoqchi bo'lmagan qatorlarni ham jimgina qayta yozib yuborishi mumkin, shuning uchun oldindan grep bilan tekshiring.
O'zgartirishdan oldin tekshirish odati
Faqat aynan kutilgan qator(lar) chiqqanini tasdiqlagandan keyin:
sed -i ga ko'r-ko'rona ishonishdan ko'ra, diff natijasini ko'rib chiqish xavfsizroq oraliq qadam.
Kerakli qatorlarni tanlash
-nsukut bo'yicha chiqishni o'chiradi, shunda faqatpbilan aniq chiqarilgan qatorlar ko'rinadi.2,3p2-qatordan 3-qatorgacha bo'lgan oraliqni tanlaydi.1dbirinchi qatorni chiqish oqimidan o'chiradi. Faylning o'ziga tegilmaydi, faqat oqim o'zgaradi.
Qatorni raqami o'rniga regular expression bilan ham tanlash mumkin:
Guruhlar va orqaga havolalar
Qavs ichidagi guruhni keyin \1, \2 va hokazo shaklida qayta ishlatish mumkin:
INFO 2026-07-29T10:00:00 orders-api 12ms
ERROR 2026-07-29T10:00:02 orders-api 340ms
ERROR 2026-07-29T10:00:03 billing-db 890ms
WARN 2026-07-29T10:00:04 orders-api 45ms
-E kengaytirilgan regular expression’larni yoqadi: ularda qavslarni qochirish shart emas (\(...\) o'rniga (...)). Bu misol sana, vaqt va daraja maydonlarining o'rnini almashtirib, ISO 8601 ga yaqin ko'rinish hosil qiladi.
Almashtirishdagi & tuzog'i
s/// ning almashtiriladigan qismida qochirilmagan & oddiy ampersand belgisini emas, mos kelgan butun matnni bildiradi:
& butun moslikka almashib, uni kvadrat qavslar ichiga oldi. Oddiy ampersand qo'yish uchun uni \& deb qochiring. Xuddi shunday ehtiyotkorlik \1, ajratuvchi va teskari chiziqlarga ham tegishli: qochirilmagan yoki ishonchsiz ma’lumotdan yig'ilgan almashtirish matni siz kutmagan tarzda kengayishi mumkin. O'zgarish arzimasdek ko'rinsa ham, uni qo'llashdan oldin almashtirishni -i siz ko'rib chiqish kerakligining yana bir sababi shu.
Bir nechta qator bilan ishlash: hold space
Hozirgacha barcha misollar bir vaqtda bitta qator bilan ishladi, sed odatda shunday ishlaydi: qatorni pattern space ga o'qiydi, buyruqlarni qo'llaydi, uni chiqaradi va keyingi qatorga o'tadi. Ba’zi tahrirlar uchun bir vaqtda bir nechta qatorni ko'rish kerak bo'ladi: bo'linib ketgan qatorni birlashtirish, ketma-ket bo'sh qatorlarni bittaga qisqartirish yoki faylni teskari tartibda chiqarish. Buning uchun sed hold space deb ataladigan ikkinchi yordamchi buferni saqlaydi.
Nyangi sikl boshlash o'rniga keyingi kirish qatorini pattern space’ga yangi qator belgisi orqali qo'shadi.Dpattern space’dagi birinchi yangi qator belgisigacha bo'lgan hamma narsani o'chiradi va yangi qator o'qimasdan siklni qayta boshlaydi. U ko'p qatorli pattern space bilan qatorma-qator ishlash uchun ishlatiladi.h/Hpattern space’ni hold space’ga nusxalaydi yoki qo'shadi.g/Ghold space’ni pattern space’ga qaytarib nusxalaydi yoki qo'shadi.
Ko'p uchraydigan qo'llanish — ketma-ket bo'sh qatorlarni bittaga qisqartirish:
Qadamma-qadam o'qisak: bo'sh qator topilganda N keyingi qatorni ham olib keladi va u ham bo'shligini tekshiradi. Agar ikki qatorli pattern space aynan ikkita bo'sh qatordan iborat bo'lsa (^\n$), D birinchisini tashlab yuboradi va qolgani bilan siklni qayta boshlaydi. Natijada istalgan uzunlikdagi bo'sh qatorlar ketma-ketligi bitta bo'sh qatorga qisqaradi va buning uchun awk’da butun faylni qamrab oladigan yechim yozish shart bo'lmaydi.
Hold space, ayniqsa, keyingi qatorni qayta ishlayotganda oldingi qatordagi ma’lumot asosida qaror qabul qilish kerak bo'lganda muhim. Masalan, oldingi qatorni joriy qator bilan birga chiqarish:
2026-07-29 10:00:04 WARN orders-api 45ms
2026-07-29 10:00:03 ERROR billing-db 890ms
2026-07-29 10:00:02 ERROR orders-api 340ms
2026-07-29 10:00:00 INFO orders-api 12ms
Chapdan o'ngga o'qisak: 1!G "birinchisidan boshqa har bir qatorda hold space’ni pattern space’ga qo'sh" degani, h keyin (o'sib borayotgan) pattern space’ni hold space’ga qaytarib nusxalaydi, $p esa yig'ilgan yakuniy natijani faqat oxirgi qatorda chiqaradi. Natijada (klassik sed usuli) fayl teskari tartibda chiqadi. Bu andozani aniq tanib olish foydali, chunki u troubleshooting qo'llanmalarida va sed ning ichki tuzilishi haqidagi intervyu savollarida uchraydi. Sababi faylni qo'lda teskari aylantirish tez-tez kerak bo'lishida emas: buni tac to'g'ridan-to'g'ri va tushunarliroq bajaradi.
Intervyuda
"sed bir vaqtda bir nechta qator bilan qanday ishlaydi?" deb so'rashsa, javob yuqoridagi pattern space va hold space modeli. sed asosan qatorlar bilan ishlaydigan vosita. Qatorlararo kontekst kerak bo'ladigan kam uchraydigan holatlar uchun u N/D va hold space mexanizmini taklif qiladi. awk esa oddiy o'zgaruvchilar va massivlarda butun kirish bo'yicha holatni tabiiy ravishda to'plab boradi.
awk: ustunli ma’lumotlar bilan ishlash
sed har bir qatorni bir butun sifatida ko'radi. awk esa har bir qatorni bo'sh joy (yoki siz ko'rsatgan boshqa ajratuvchi) bo'yicha maydonlarga bo'ladi. Shu sabab ustunlar ustida hisob-kitob qilish uchun u ancha qulay.
Kerakli maydonlarni chiqarish
$1, $2 va hokazo — bo'sh joy bilan ajratilgan maydonlar, $0 esa butun qator. Sukut bo'yicha maydon ajratuvchisi bir yoki bir nechta bo'sh joy yoki tab belgisi.
Shart bo'yicha filtrlash
grep dan farqli ravishda awk mos kelgan qatorni topish bilan cheklanmaydi: undan faqat sizga kerakli ustunlarni ajratib oladi.
O'z maydon ajratuvchingiz: -F
CSV yoki key=value ko'rinishidagi ma’lumotlar uchun:
printf 'name=orders-api,status=up,latency=12\nname=billing-db,status=down,latency=340\n' > services.csv
awk -F',' '{ print $1 }' services.csv
Yig'indi va sanash: BEGIN/END
Agar birorta ham ERROR qatori uchramasa, count+0 natija bo'sh satr emas, 0 bo'lib chiqishini ta’minlaydi. awk da hech qachon qiymat berilmagan o'zgaruvchi sukut bo'yicha bo'sh/nol qiymatga ega bo'ladi.
BEGIN bloki kirish o'qilishidan oldin bir marta, END bloki esa butun kirish o'qib bo'lingandan keyin bir marta bajariladi:
awk 'BEGIN { print "Analysis started" }
$3 == "ERROR" { total += $4 + 0 }
END { print "Total ERROR latency (ms):", total+0 }' requests.log
Bu yerda $4 (masalan, 340ms) avtomatik ravishda son bo'lmaydi. awk satrning boshidagi son qismini o'qiydi va oxiridagi ms ni e’tiborga olmaydi, chunki qiymat faqat arifmetik amalda ishlatilgandagina songa aylantiriladi.
Ustun bo'yicha guruhlash
count[$3] — log darajasi kalit bo'lgan assotsiativ massiv. awk dagi har bir massiv assotsiativ bo'ladi. for (level in count) massiv kalitlari bo'ylab aylanadi; bunda kalitlarning tartibi kafolatlanmaydi.
Natijani printf bilan formatlash
print qulay, lekin ustun kengligi yoki sonlar formatini deyarli boshqarib bo'lmaydi. awk dagi printf C tili va shell’dagi xuddi shu nomli funksiya kabi ishlaydi va odam o'qiydigan hisobot uchun yaxshiroq tanlov:
%-12s satrni 12 belgili maydonda chapga, %5s esa 5 belgili maydonda o'ngga tekislaydi. Bu C dagi printf yoki shell’ning ichki buyrug'idagi format belgilarining aynan o'zi. print dan farqli ravishda printf oxiriga yangi qator belgisini o'zi qo'shmaydi, shuning uchun format satri oxiridagi \n shart.
Bir nechta fayl bilan ishlash: FNR va NR
awk bir nechta kirish faylini qabul qiladi. Bu turli manbalardagi ma’lumotlarni birlashtirish yoki solishtirishda muhim:
printf 'name=orders-api,status=up,latency=12\nname=billing-db,status=down,latency=340\n' > services.csv
awk -F',' '{ print FILENAME, FNR, NR }' requests.log services.csv
requests.log 1 1
requests.log 2 2
requests.log 3 3
requests.log 4 4
services.csv 1 5
services.csv 2 6
NR — shu paytgacha o'qilgan barcha fayllar bo'yicha umumiy yozuvlar soni. FNR esa har bir yangi fayl boshida 1 ga qaytadi. FILENAME hozir o'qilayotgan fayl nomini saqlaydi. FNR == 1 sharti "yangi fayl hozirgina boshlandi" degan holatni aniqlashning standart usuli. U har bir fayl uchun sarlavha chiqarish yoki har bir fayldagi sarlavha qatorini alohida tashlab o'tish uchun foydali:
Bitta faylda yozilib sinalgan skript keyinchalik bir nechta faylga qo'llanganda NR va FNR ni adashtirish ko'p xatolarga sabab bo'ladi. Qator raqamiga bog'liq har qanday mantiq (sarlavhani tashlab o'tish, ma’lum qatorni topish) jimgina buziladi, chunki NR qaytadan boshlanish o'rniga o'sishda davom etadi.
sed yoki awk: qachon qaysi birini tanlash kerak
| Vazifa | Yaxshiroq vosita | Sababi |
|---|---|---|
| Bitta qator ichida matnni almashtirish | sed |
Qatorni bir butun deb ko'radi; oddiy almashtirish uchun sodda |
| Konfiguratsiya faylidagi bitta qiymatni yangilash | sed -i (ehtiyotkorlik bilan) |
Bitta qator, bitta almashtirish — boshqa hech narsa kerak emas |
| Muayyan ustunlarni ajratib olish yoki ular ustida hisoblash | awk |
Maydonlarga o'zi bo'ladi, arifmetika va massivlarni qo'llab-quvvatlaydi |
| Bir nechta shart bo'yicha yig'indi yoki sanoq | awk |
BEGIN/END va assotsiativ massivlar aynan shu ish uchun yaratilgan |
| Qatorni o'zgartirmasdan faqat topish | grep |
Ikkala vosita ham buni qila oladi, lekin grep soddaroq va tezroq |
Ikkala vosita ham to'liq ma’noda alohida dasturlash tillari. Bu yerda ko'rsatilgani tizim administratorining kundalik ishida kerak bo'ladigan qismi xolos.
Amaliy vaziyat: sozlamani almashtirish va logni umumlashtirish
Muammo: app.conf da env=staging ni env=production ga o'zgartirish kerak, lekin faqat aynan bitta qator mos kelishini tasdiqlagandan keyin. So'ng o'zgarish yozuvi (change record) uchun requests.log bo'yicha har bir darajadagi hodisalar sonini chiqarish kerak.
-
Faylga tegishdan oldin almashtiriladigan qatorni tasdiqlang:
Natija
1bo'lsa, andoza faylni xavfsiz tahrirlash uchun yetarlicha aniq.0yoki2va undan ko'p bo'lsa, to'xtang va andozani aniqlashtiring. Aks holdased -iyo hech narsani o'zgartirmaydi, yo kutilganidan ko'p qatorni qayta yozadi va zaxira nusxani o'tkazib yuborgan bo'lsangiz, ikkinchi imkoniyat bo'lmaydi. -
Zaxira nusxa bilan tahrirlang, so'ng faqat kutilgan qator o'zgarganini tasdiqlang:
Andozani
^...$bilan qotirishenv=stagingboshqa uzunroq qiymatning bir qismi sifatida uchragan joylarda almashtirish ishlab ketishining oldini oladi. -
O'zgarish tiketi uchun logni darajalar bo'yicha umumlashtiring:
Asosiy g'oya — vazifalarning taqsimlanishi: sed bitta qatorga ko'rib chiqilgan va ortga qaytariladigan bitta o'zgarish kiritdi, awk esa ustun bo'yicha umumiy natijani hisobladi. Konfiguratsiyani tahrirlash uchun awk ni yoki logni sanash uchun sed ni olish ikkala holatda ham noto'g'ri vosita tanlash bo'lardi.
Keng tarqalgan xatolar
- Production faylga zaxira nusxasiz yoki oldindan sinab ko'rmasdan (dry run) to'g'ridan-to'g'ri
sed -iqo'llash. s///dagbayrog'ini unutib, qatordagi faqat birinchi moslik o'zgarganini sezmay qolish.$3 == "ERROR"kabiawksolishtiruvida satrni qo'shtirnoqsiz yozish — satrlarni solishtirishda qo'shtirnoq muhim.awkmaydonlari raqamlanishi faylning haqiqiy ajratuvchisiga mos keladi deb tekshirmasdan qabul qilish (masalan, vergul bilan ajratilgan faylni bo'sh joy bo'yicha bo'linadi deb o'ylash).countyokitotalkabiawkyig'uvchisini+0siz chiqarib, u hech qachon oshirilmaganda bo'sh natija chiqqanidan hayron qolish.sedvagrepni bir xil vosita deb hisoblab, oddiygrepyetarli bo'lgan joydased -n '/pattern/p'ni ishlatish.
Mashqlar
sed -i.bakyordamidaapp.confdagidebug=truenidebug=falsega o'zgartiring, so'ng o'zgarishnidiffbilan tasdiqlang.sed -nyordamidarequests.logdan faqatWARNvaERRORqatorlarini chiqaring, so'ng xuddi shu natijaniawkbilan hosil qiling. Ikki yondashuvni solishtiring.awkyordamida har bir xizmat (orders-api,billing-db)requests.logda necha marta uchrashini sanang.sed -Eyordamidarequests.logdagi sana va vaqtniTbilan birlashtirilgan bitta maydonga aylantiring. Yuqoridagi misolga o'xshash, lekin o'zingiz yozgan andoza bilan.
Mashqni bajardim deyish uchun: har bir natija uchun qaysi vositani (sed yoki awk) tanlaganingizni va nima uchun aynan shu vazifaga u yaxshiroq mos kelganini tushuntirib bera olishingiz kerak.
Manbalar
- GNU sed qo'llanmasi: https://www.gnu.org/software/sed/manual/sed.html
- GNU sed: faylni joyida tahrirlash: https://www.gnu.org/software/sed/manual/sed.html#sed-Basics
- GNU Awk User's Guide: https://www.gnu.org/software/gawk/manual/gawk.html
- POSIX: sed: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/sed.html
- POSIX: awk: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/awk.html