grep, sed at awk: mga halimbawa ng pagproseso ng teksto sa Linux terminal
Hinahanap ng grep ang mga linya ayon sa pattern (grep -rn error /var/log), binabago ng sed ang teksto sa stream o sa file (sed -i 's/old/new/g' file), at hinahati ng awk ang linya sa mga column at nagbibilang (awk '{print $1}' access.log). Sama-sama sa isang pipeline, pinapalitan nila ang script: sinasala ng grep ang mga linya, ine-edit ng sed ang teksto, at kinukuha ng awk ang mga field at pinagsasama-sama ang datos.
Ang grep, sed, at awk ay tatlong klasikong utility ng Linux para sa pagproseso ng teksto. Ang grep ay naghahanap ng mga linya ayon sa pattern, ang sed ay pumapalit at nagtatanggal ng teksto sa stream nang hindi nagbubukas ng editor, at ang awk ay hinahati ang linya sa mga column at kayang magbilang. Narito ang mga grep sed awk halimbawa na talagang kailangan kapag sinusuri ang mga log, config, at output ng mga command, kasama ang mga karaniwang pagkakamali.
Kailan gagamitin ang alin
Lahat ng tatlong tool ay nagbabasa ng teksto linya por linya at naglalabas ng resulta sa standard output, kaya madali silang pagsamahin gamit ang |. Ang pagkakaiba ay nasa gawain na mas mahusay nilang nalulutas.
| Gawain | Tool | Halimbawa |
|---|---|---|
| Maghanap ng linyang may teksto | grep | grep ERROR app.log |
| Palitan ang teksto | sed | sed 's/http:/https:/g' file |
| Magtanggal o magpakita ng linya ayon sa numero | sed | sed -n '10,20p' file |
| Kunin ang isang column | awk | awk '{print $1}' access.log |
| Magbilang ng kabuuan, average, o grupo | awk | awk '{s+=$10} END {print s}' |
Simpleng panuntunan: kung i-filter lang ang kailangan, gamitin ang grep; kung palitan ang teksto, sed; kung may column ang teksto o kailangan ng aritmetika, awk.
grep: paghahanap ng mga linya ayon sa pattern
Mga pangunahing halimbawa ng grep
# Mga linyang may salitang error sa file
grep error /var/log/syslog
# Hindi sensitibo sa malaki/maliit na letra: Error, ERROR, error
grep -i error app.log
# May numero ng linya
grep -n "Connection refused" app.log
# Paulit-ulit sa direktoryo, may pangalan ng file
grep -rn "DB_HOST" /etc/myapp/
# Pangalan lang ng mga file na may tugma
grep -rl "TODO" src/
# Baligtarin: lahat MALIBAN sa mga komento at walang laman na linya
grep -v -e '^#' -e '^$' /etc/ssh/sshd_config
# Bilangin ang mga linyang tumugma
grep -c " 500 " access.log
Ang flag na -w ay naghahanap ng buong salita: hindi makikita ng grep -w log ang login. Ang flag na -F ay nagpapatay ng regular expression at naghahanap ng eksaktong string, kapaki-pakinabang kapag may tuldok, panaklong, o asterisk sa pattern.
Konteksto sa paligid ng nahanap na linya
Bihirang maintindihan ang error mula sa isang linya lang sa log; kailangan ang stack trace o ang request na nagdulot nito. Para dito may mga flag ng konteksto:
# 3 linya pagkatapos ng tugma (After)
grep -A 3 "Traceback" app.log
# 2 linya bago ng tugma (Before)
grep -B 2 "OOM" /var/log/kern.log
# tig-5 linya sa magkabilang panig (Context)
grep -C 5 "segfault" /var/log/syslog
Pinaghihiwalay ng grep ang mga grupo ng tugma gamit ang linyang --, kaya madaling basahin ang output.
grep at regular expression
Bilang default, naiintindihan ng grep ang basic regular expression (BRE). Gamit ang -E, naka-on ang extended (ERE), kung saan gumagana ang +, ?, |, at panaklong nang walang backslash.
| Konstruksyon | Kahulugan | Halimbawa |
|---|---|---|
^ | simula ng linya | grep '^root' /etc/passwd |
$ | dulo ng linya | grep 'bash$' /etc/passwd |
. | kahit anong karakter | grep 'h.t' |
* | 0 o higit pang ulit | grep 'ab*c' |
+ (ERE) | 1 o higit pa | grep -E '[0-9]+' |
| (ERE) | o | grep -E 'error|warn' |
[...] | isang karakter mula sa set | grep '[Ee]rror' |
# Mga linyang may error o babala
grep -E "ERROR|WARN" app.log
# Mga IP address lang mula sa log, isa bawat linya (-o — ipakita lang ang tugma)
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' access.log
grep -P: kunin ang value sa pagitan ng kilalang bahagi
May flag na -P ang GNU grep para sa regular expression na istilong Perl. Kasama nito ang \K (“kalimutan ang lahat ng tumugma hanggang dito”) at lookahead, kaya makukuha ang value lang:
$ echo 'user_id=4821 status=ok' | grep -oP 'user_id=\K[0-9]+'
4821
$ grep -oP '"version":\s*"\K[^"]+' package.json
2.4.1
Hindi lahat ng build ng grep ay may -P (halimbawa, wala nito ang BSD grep sa macOS), kaya sa mga portable na script mas mabuting gamitin ang sed o awk.
grep -q sa mga kondisyon ng script
Ang grep -q ay walang ipinapakita at nagbabalik lang ng exit code: 0 kung may nahanap, 1 kung wala. Sa ganitong paraan, direktang maisusulat ang pagsusuri sa loob ng if:
if grep -q "^PermitRootLogin no" /etc/ssh/sshd_config; then
echo "naka-disable ang root login"
fi
Mas maikli ito kaysa itago ang output sa variable at tingnan kung walang laman, at humihinto ang grep sa unang tugma.
sed: pagpapalit at pagtanggal ng teksto
Pagpapalit: ang command na s
Ang pangunahing command ng sed ay s/pattern/kapalit/mga-flag. Kung walang flag na g, isang tugma lang sa bawat linya ang napapalitan.
# Ipakita ang teksto na may pagpapalit (hindi nagbabago ang file)
sed 's/foo/bar/' file.txt
# Palitan ang lahat ng tugma sa linya
sed 's/foo/bar/g' file.txt
# Hindi sensitibo sa letra (GNU sed)
sed 's/error/ERROR/gI' app.log
# Ibang delimiter kung may slash sa teksto
sed 's|/var/www|/srv/www|g' nginx.conf
sed -i: pagpapalit mismo sa file
Isinusulat ng flag na -i ang resulta pabalik sa file. Para hindi mawala ang orihinal, maglagay ng suffix para sa backup:
# Gagawa ng config.ini.bak at babaguhin ang config.ini
sed -i.bak 's/^debug=true/debug=false/' config.ini
# Palitan sa lahat ng .conf sa direktoryo
find /etc/myapp -name "*.conf" -exec sed -i 's/old-host/new-host/g' {} +
Bago ang malawakang pag-edit, patakbuhin muna ang command nang walang -i at tingnan ang output. Sa macOS (BSD sed), kailangan ng argumento ang -i: sed -i '' 's/a/b/' file.
Pagtatrabaho sa mga linya ayon sa numero at pattern
# Ipakita ang mga linya 10–20 (-n pinapatay ang auto-print, p — print)
sed -n '10,20p' file.txt
# Tanggalin ang linya 5
sed '5d' file.txt
# Tanggalin ang huling linya
sed '$d' file.txt
# Tanggalin ang mga walang laman na linya at komento
sed -e '/^$/d' -e '/^#/d' nginx.conf
# Palitan lang sa mga linyang may "listen"
sed '/listen/s/80/8080/' nginx.conf
# Maglagay ng linya pagkatapos ng tugma (GNU sed)
sed '/^\[mysqld\]/a max_connections = 500' my.cnf
Back reference at &
Ang bahagi ng pattern na nasa panaklong ay maaaring ilagay sa kapalit gamit ang \1, \2, at ang simbolong & ay tumutukoy sa buong tugma.
# Palitan ang pangalan at apelyido (ERE gamit ang -E)
$ echo "Santos Juan" | sed -E 's/(\S+) (\S+)/\2 \1/'
Juan Santos
# Ilagay sa square bracket ang lahat ng numero
$ echo "port 8080, timeout 30" | sed -E 's/[0-9]+/[&]/g'
port [8080], timeout [30]
# Gawing 14.10.2026 ang petsang 2026-10-14
$ echo 2026-10-14 | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3.\2.\1/'
14.10.2026
awk: mga column, kondisyon, at pagbibilang
Pag-print ng kailangang column
Hinahati ng awk ang bawat linya sa mga field ayon sa space at tab: ang $1 ang unang field, $2 ang pangalawa, $NF ang huli, at $0 ang buong linya.
# Mga IP address mula sa nginx log (unang column)
awk '{print $1}' /var/log/nginx/access.log
# Pangalan ng user at shell mula sa /etc/passwd (delimiter ang colon)
awk -F: '{print $1, $7}' /etc/passwd
# Huling column
df -h | awk '{print $NF}'
# Sariling delimiter sa output
awk -F: -v OFS=';' '{print $1, $3}' /etc/passwd
Mga kondisyon: i-print lang ang kailangang linya
Maaaring maglagay ng kondisyon bago ang block sa curly brace, at ang aksyon ay gagawin lang sa mga angkop na linya.
# Mga user na may UID mula 1000 pataas (karaniwang user, hindi system)
awk -F: '$3 >= 1000 {print $1}' /etc/passwd
# Mga request na may status code 500 pataas (ika-9 na field sa combined format)
awk '$9 >= 500' access.log
# Mga linyang tumugma ang ika-6 na column sa regex
awk '$6 ~ /POST/' access.log
# Mga file na mas malaki sa 100 MB mula sa output ng ls -l
ls -l | awk '$5 > 100*1024*1024 {print $9}'
BEGIN, END, at NR: awk bilang maliit na programa
Ang block na BEGIN ay tumatakbo bago basahin ang unang linya, at ang END ay pagkatapos ng huling linya. Ang NR ang numero ng kasalukuyang linya, at sa block na END ay ang kabuuang bilang nito.
# Kabuuan ng laki ng mga sagot (ika-10 na field) sa megabyte
awk '{sum += $10} END {printf "%.1f MB\n", sum/1024/1024}' access.log
# Average ng oras ng sagot mula sa huling column
awk '{s += $NF} END {if (NR) print s/NR}' timings.log
# Laktawan ang header ng CSV
awk -F, 'NR > 1 {print $2}' users.csv
# Bilangin ang request kada IP: associative array
awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log | sort -rn | head
Ang huling halimbawa ay klasiko sa pagsusuri ng log: pinapalitan ng array na count na may IP bilang susi ang kombinasyong sort | uniq -c, at madaling palawigin, halimbawa para sa kabuuang trapiko kada address.
Mga pipeline: grep, sed, at awk nang magkasama
Ang tunay na lakas ay nasa kombinasyon. Bawat tool ay gumagawa ng sariling bahagi, at ipinapasa ng | ang resulta.
Nangungunang 10 IP na may 5xx na error
grep ' 50[0-9] ' /var/log/nginx/access.log \
| awk '{print $1}' \
| sort | uniq -c | sort -rn | head -10
412 203.0.113.45
118 198.51.100.7
36 192.0.2.19
Dito, magaspang na sinasala ng grep ang mga linya, kinukuha ng awk ang field, at binibilang ng sort | uniq -c ang mga pag-uulit. Maaari rin itong isulat sa iisang awk: awk '$9 ~ /^5/ {c[$1]++} END {for (i in c) print c[i], i}' access.log | sort -rn | head — mas tumpak ito, dahil eksaktong column ng status code ang sinusuri.
Aling mga URL ang madalas buksan
awk '{print $7}' access.log | sed 's/?.*//' | sort | uniq -c | sort -rn | head
Pinuputol ng sed dito ang query string, para ang /search?q=a at /search?q=b ay mabilang bilang iisang pahina.
Mga value mula sa config nang walang komento
grep -v '^\s*#' /etc/myapp/app.env | grep '=' | awk -F= '{print $1}'
Mga error sa isang partikular na oras
grep '14/Oct/2026:03:' access.log | awk '$9 >= 500 {print $4, $7, $9}'
Mga karaniwang pagkakamali
- Double quote sa halip na single quote sa awk. Sa
awk "{print $1}", papalitan ng shell ang sarili nitong$1bago tumakbo ang awk. Isulat ang programa ng awk at mga expression ng sed sa single quote. - Nakalimutan ang
gsa sed. Kung wala ito, isang tugma lang sa linya ang mapapalitan, at ang iba ay mananatili. sed -inang walang pagsusuri. Maaaring masira nang tahimik ng maling regex ang file. Patakbuhin muna nang walang-i, o gamitin ang-i.bak.- Hindi gumagana ang
+at|sa grep. Extended syntax ito: kailangan anggrep -E(osed -E). - Tuldok sa pattern. Makikita rin ng
grep 192.168.1.1ang192x168y1z1, dahil ang tuldok ay “kahit anong karakter”. Gamitin anggrep -Fo i-escape bilang\.. - Mga space sa column. Kung maaaring may space ang field (CSV, path), tahasang itakda ang delimiter:
awk -F,oawk -F'\t'. - Walang-silbing cat. Gumagana ang
cat file | grep x, pero mas maikli at hindi na gumagawa ng dagdag na proseso anggrep x file.
Ano ang maaaring palitan ng grep, sed, at awk
Hindi angkop ang mga tool na ito para sa JSON: mas mainam na gamitin ang jq para sa istruktura (jq '.items[] | select(.status=="active") | .name'), at ang yq para sa YAML. Para sa mabilis na recursive na paghahanap sa malalaking proyekto, madalas gamitin ang ripgrep (command na rg), na default na sumusunod sa .gitignore. Kung mas gusto ang sintaks ng Perl, pinapalitan ng perl -pe 's/a/b/g' at perl -lane 'print $F[0]' ang sed at awk sa isang linya. Pero ang grep, sed, at awk ay halos nasa bawat server nang hindi na kailangang mag-install, kaya ito ang dapat unang matutunan.
Buod
Hinahanap ng grep ang mga linya, binabago ito ng sed, at ang awk ang humahawak ng mga column at pagbibilang. Tandaan ang pangunahing hanay: grep -rniE at -A/-B/-C, sed 's/.../.../g' na may -i.bak at -n 'Np', at awk -F na may $1, $NF, mga kondisyon, at block na END. Mula sa mga ito nabubuo ang halos anumang pagsusuri ng log. Ang mga grep sed awk halimbawang ito, kasama ang find, jq, at curl, ay tinalakay nang praktikal sa aralin ng kurso sa Linux tungkol sa pagproseso ng teksto sa terminal.
Mga madalas itanong
Ano ang pagkakaiba ng grep at egrep?
Ang egrep ay lumang alias ng grep -E (extended regular expression). Naglalabas ng babala ang mga modernong bersyon ng GNU grep kapag tinawag ang egrep, kaya isulat na lang ang grep -E.
Paano maghanap ng teksto sa lahat ng file ng isang direktoryo sa Linux?
Gamitin ang grep -rn "teksto" /path: ang -r ay recursive, at ang -n ay nagpapakita ng numero ng linya. Para limitahan ang uri ng file, idagdag ang --include="*.php".
Paano palitan ang teksto sa maraming file nang sabay?
Pagsamahin ang paghahanap at sed: grep -rl "old" . | xargs sed -i 's/old/new/g'. Bago ito, makabubuting mag-commit o gumawa ng backup.
Paano mag-print ng maraming column sa awk na may tab sa pagitan?
Itakda ang output delimiter: awk -v OFS='\t' '{print $1, $3}' file. Kung walang OFS, ang mga field ay pinaghihiwalay ng space.
Paano tatanggalin ang mga space sa dulo ng linya gamit ang sed?
Ang command na sed -i 's/[[:space:]]*$//' file ay nagtatanggal ng mga trailing space at tab sa lahat ng linya ng file.
Detalyadong tinatalakay ang paksang ito, may praktis, sa kursong “Linux: с нуля до уверенного администрирования”.
Pumunta sa kurso