sed va awk — matnni o'zgartirish va ustunlar

~18 daq · Linux · Matn bilan ishlash

Muammodan boshlaylik

Ikki vazifa:

  1. 50 ta konfiguratsiya faylida localhost:3306 ni db.dokon.uz:3306 ga almashtirish kerak. Har birini muharrirda ochasizmi?
  2. sotuvlar.csv da har bir shahar bo'yicha sotuvlar yig'indisini hisoblash kerak. cut va uniq faqat sanaydi — qo'shish ular qo'lidan kelmaydi.

Birinchi vazifa — sed uchun, ikkinchisi — awk uchun. Ikkalasi ham to'liq dasturlash tillari, lekin 90% holatlarda bir nechta oddiy naqsh yetarli.


sed — oqim muharriri

sed (stream editor) matnni qatorma-qator o'qiydi va o'zgartiradi — muharrirni ochmasdan.

Almashtirish: s/eski/yangi/

echo "Salom dunyo" | sed 's/dunyo/Toshkent/'
Salom Toshkent
sed 's/localhost/db.dokon.uz/' config.env          # natija ekranga
sed 's/localhost/db.dokon.uz/g' config.env         # g — qatordagi BARCHASI

g siz — har qatorda faqat birinchi topilgan almashtiriladi.

Faylni o'zgartirish: -i

sed -i 's/localhost/db.dokon.uz/g' config.env
sed -i.bak 's/localhost/db.dokon.uz/g' config.env    # config.env.bak zaxira bilan

[!WARNING] sed -i faylni joyida o'zgartiradi — qaytarish yo'q. Avval -i siz ishga tushirib, natijani ekranda ko'ring. Yoki -i.bak bilan zaxira oling.

[!INFO] macOS da sed -i boshqacha: sed -i '' 's/a/b/g' fayl. Linux da — sed -i 's/a/b/g' fayl.

Ko'p fayllarda

grep -rl "localhost:3306" config/ | xargs sed -i 's/localhost:3306/db.dokon.uz:3306/g'

grep -rl — qaysi fayllarda; xargs sed -i — hammasida almashtirish (15-dars).

Ajratuvchini o'zgartirish

Yo'llarda / ko'p — \/ bilan yozish noqulay. Istalgan belgi ajratuvchi bo'lishi mumkin:

sed 's/\/var\/www/\/opt\/app/g' nginx.conf       # ❌ o'qish qiyin
sed 's|/var/www|/opt/app|g' nginx.conf            # ✅

Boshqa sed buyruqlari

sed -n '10p' fayl.txt              # faqat 10-qator
sed -n '10,20p' fayl.txt           # 10–20 qatorlar
sed '5d' fayl.txt                  # 5-qatorni o'chirish
sed '/^#/d' nginx.conf             # # bilan boshlanuvchi (izoh) qatorlarni o'chirish
sed '/^$/d' fayl.txt               # bo'sh qatorlarni o'chirish
sed 's/^/  /' fayl.txt             # har qator boshiga 2 bo'shliq
sed 's/[[:space:]]*$//' fayl.txt   # qator oxiridagi bo'shliqlarni o'chirish
sed -i 's/\r$//' skript.sh         # Windows qator oxirlarini tuzatish

-n + p — "faqat ko'rsatilganini chiqar".

Shartli almashtirish

sed '/^PORT=/s/3000/8080/' .env    # faqat PORT= bilan boshlanuvchi qatorda

Amaliy misol: sozlamani o'zgartirish

sudo sed -i 's/^#\?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config

SSH da parol bilan kirishni o'chirish (42-dars): izohlangan (#) yoki yo'q — qatorni PasswordAuthentication no ga almashtiradi.


awk — ustunlar bilan ishlash

awk har bir qatorni avtomatik ustunlarga (maydonlarga) bo'ladi:

  • $1, $2, ... — 1, 2-ustun
  • $0 — butun qator
  • $NF — oxirgi ustun
  • NR — qator raqami
  • NF — ustunlar soni

Standart ajratuvchi — bo'shliqlar (bittami, o'ntami — farqi yo'q). Bu cut dan katta afzallik.

echo "Otabek  25   Toshkent" | awk '{print $1, $3}'
Otabek Toshkent

Tuzilma

awk 'SHART { HARAKAT }' fayl
ps aux | awk '{print $2, $11}'                   # PID va buyruq
ls -l | awk '{print $5, $9}'                     # hajm va nom
df -h | awk '{print $5, $6}'                     # foiz va mount
awk -F: '{print $1}' /etc/passwd                 # -F — ajratuvchi
awk -F',' '{print $2}' sotuvlar.csv

Shartlar

awk '$3 > 100' data.txt                          # 3-ustun 100 dan katta
awk -F',' '$2 == "Toshkent"' sotuvlar.csv        # faqat Toshkent
awk '/ERROR/' app.log                            # grep kabi
awk 'NR > 1' sotuvlar.csv                        # sarlavhasiz
awk 'NF > 0' fayl.txt                            # bo'sh bo'lmagan qatorlar
awk '$9 >= 500' access.log                       # 5xx javoblar (Nginx)

Hisoblash — awk ning asosiy kuchi

# Jami
awk -F',' 'NR > 1 { jami += $4 } END { print "Jami:", jami }' sotuvlar.csv
Jami: 17
  • NR > 1 — sarlavhani o'tkazib yuborish
  • jami += $4 — har qatorda qo'shish
  • END { } — barcha qatorlardan keyin bir marta
# Har bir shahar bo'yicha yig'indi
awk -F',' 'NR > 1 { s[$2] += $4 } END { for (sh in s) print sh, s[sh] }' sotuvlar.csv
Buxoro 1
Samarqand 7
Toshkent 9

s[$2] — massiv (lug'at): kalit — shahar, qiymat — yig'indi. Bu — SQL dagi GROUP BY + SUM.

# O'rtacha
awk '{ s += $1; n++ } END { print s / n }' sonlar.txt

# Papkadagi fayllar umumiy hajmi (MB)
ls -l | awk '{ s += $5 } END { printf "%.1f MB\n", s / 1024 / 1024 }'

# Nginx: o'rtacha javob hajmi
awk '{ s += $10 } END { print s / NR }' access.log

Formatlab chiqarish

awk -F',' 'NR > 1 { printf "%-12s %5d\n", $2, $4 }' sotuvlar.csv
Toshkent         3
Samarqand        5
...

printf — C dagi kabi: %s matn, %d butun son, %.2f kasr, %-12s — 12 belgilik chapga tekislangan.


sed yoki awk?

Vazifa Vosita
Matnni almashtirish (find & replace) sed
Fayldagi qatorlarni o'chirish, chiqarish sed
Konfiguratsiyani skriptda o'zgartirish sed -i
Ustunni ajratish (bo'shliqlar bilan) awk
Hisoblash: yig'indi, o'rtacha awk
Guruhlash (GROUP BY) awk
Murakkab mantiq Python yoki boshqa til

[!TIP] Agar awk buyrug'i bir necha qatordan oshib ketsa — bu Python skript yozish vaqti kelganining belgisi. awk — tez bir qatorli tahlil uchun.


Nima uchun shunday?

Nima uchun 1970-yillardagi sed va awk bugun ham ishlatiladi, Python bor bo'lsa ham?

Chunki ular har bir serverda allaqachon bor va bir qatorda ishlaydi. Serverda log tahlili uchun Python skript yozish — fayl yaratish, ochish, o'qish, ajratish, chop etish. awk da — awk '{s+=$10} END {print s}' access.log, 5 soniya. Bundan tashqari, ular oqim bilan ishlaydi: 20 GB faylni xotiraga yuklamasdan qatorma-qator qayta ishlaydi. sed esa skriptlarda va Dockerfile larda konfiguratsiyani avtomatik o'zgartirishning standart usuli bo'lib qoldi. Ular "katta" dasturlash tili emas — terminalning "kalkulyatori" va "qidir-almashtir" i.


Xulosa

Eslab qoling:

  • sed 's/eski/yangi/g' — almashtirish; -i — faylda (ehtiyot!), -i.bak — zaxira bilan
  • sed 's|a|b|g' — yo'llar uchun boshqa ajratuvchi
  • sed -n '10,20p' — qatorlarni chiqarish; '/^#/d' — izohlarni o'chirish
  • awk '{print $1, $3}' — ustunlar; -F',' — ajratuvchi; $NF — oxirgi
  • awk '$3 > 100' — filtrlash; NR > 1 — sarlavhasiz
  • awk '{s += $2} END {print s}' — yig'indi
  • s[$1] += $2 — guruhlash (GROUP BY)

Keyingi dars

17-dars: Mashqlar — log fayllarni tahlil qilish