grep, sed और awk: टर्मिनल में टेक्स्ट प्रोसेसिंग के उदाहरण
grep पैटर्न से लाइनें खोजता है (grep -rn error /var/log), sed स्ट्रीम या फ़ाइल में टेक्स्ट बदलता है (sed -i 's/old/new/g' file), और awk कॉलम काटता है और गिनती करता है (awk '{print $1}' access.log)। तीनों pipeline में मिलकर स्क्रिप्ट की जगह ले लेते हैं: grep लाइनें छानता है, sed टेक्स्ट सुधारता है, awk फ़ील्ड निकालता है और जोड़ता है।
grep, sed और awk Linux की तीन पारंपरिक टेक्स्ट-प्रोसेसिंग यूटिलिटी हैं। grep पैटर्न वाली लाइनें खोजता है, sed एडिटर खोले बिना स्ट्रीम में टेक्स्ट बदलता और हटाता है, और awk हर लाइन को कॉलम में बाँटता है और गिनती भी कर सकता है। नीचे grep sed awk उदाहरण दिए हैं, जो लॉग, कॉन्फ़िग और कमांड के आउटपुट के साथ काम करते समय असल में चाहिए होते हैं, साथ में आम गलतियाँ भी।
कब कौन-सा टूल इस्तेमाल करें
तीनों टूल लाइन-दर-लाइन टेक्स्ट पढ़ते हैं और नतीजा standard output में लिखते हैं, इसलिए इन्हें | से आसानी से जोड़ा जा सकता है। फ़र्क इस बात में है कि कौन-सा काम कौन सबसे अच्छा करता है।
| काम | टूल | उदाहरण |
|---|---|---|
| टेक्स्ट वाली लाइनें खोजना | grep | grep ERROR app.log |
| टेक्स्ट बदलना | sed | sed 's/http:/https:/g' file |
| नंबर से लाइनें हटाना या दिखाना | sed | sed -n '10,20p' file |
| कोई कॉलम निकालना | awk | awk '{print $1}' access.log |
| जोड़, औसत, समूह बनाना | awk | awk '{s+=$10} END {print s}' |
सरल नियम: केवल छानना हो तो grep, टेक्स्ट बदलना हो तो sed, और टेक्स्ट में कॉलम हों या गणित चाहिए तो awk।
grep: पैटर्न से लाइनें खोजना
grep के बुनियादी उदाहरण
# फ़ाइल में वह शब्द वाली लाइनें जिसमें error है
grep error /var/log/syslog
# केस को अनदेखा करें: Error, ERROR, error
grep -i error app.log
# लाइन नंबर के साथ
grep -n "Connection refused" app.log
# डायरेक्टरी में रिकर्सिव खोज, फ़ाइल नाम के साथ
grep -rn "DB_HOST" /etc/myapp/
# केवल वे फ़ाइल नाम जिनमें मिलान है
grep -rl "TODO" src/
# उलटा: वह सब जो टिप्पणी और खाली लाइन नहीं है
grep -v -e '^#' -e '^$' /etc/ssh/sshd_config
# मेल खाने वाली लाइनों की गिनती
grep -c " 500 " access.log
-w फ्लैग पूरा शब्द ढूँढता है: grep -w log, login को नहीं पकड़ेगा। -F फ्लैग regular expressions बंद कर देता है और स्ट्रिंग को शब्दशः खोजता है, जो तब काम आता है जब पैटर्न में बिंदु, कोष्ठक या तारे हों।
मिली लाइन के आसपास का संदर्भ
लॉग की गलती अक्सर एक लाइन से समझ नहीं आती, उसके लिए वह स्टैक या अनुरोध चाहिए जो उस तक ले गया। इसके लिए संदर्भ वाले फ्लैग हैं:
# मिलान के बाद 3 लाइनें (After)
grep -A 3 "Traceback" app.log
# मिलान से पहले 2 लाइनें (Before)
grep -B 2 "OOM" /var/log/kern.log
# दोनों तरफ़ 5-5 लाइनें (Context)
grep -C 5 "segfault" /var/log/syslog
grep अलग-अलग मिलान-समूहों को -- की लाइन से अलग करता है, जिससे आउटपुट पढ़ना आसान रहता है।
grep और regular expressions
grep डिफ़ॉल्ट रूप से बेसिक regex (BRE) समझता है। -E से extended regex (ERE) चालू होता है, जहाँ +, ?, | और कोष्ठक बिना backslash के काम करते हैं।
| संरचना | अर्थ | उदाहरण |
|---|---|---|
^ | लाइन की शुरुआत | grep '^root' /etc/passwd |
$ | लाइन का अंत | grep 'bash$' /etc/passwd |
. | कोई भी एक अक्षर | grep 'h.t' |
* | 0 या उससे अधिक बार | grep 'ab*c' |
+ (ERE) | 1 या उससे अधिक बार | grep -E '[0-9]+' |
| (ERE) | या | grep -E 'error|warn' |
[...] | सेट में से एक अक्षर | grep '[Ee]rror' |
# error या warning वाली लाइनें
grep -E "ERROR|WARN" app.log
# केवल IP पते, हर एक नई लाइन पर (-o का मतलब केवल मिलान छापना)
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' access.log
grep -P: दो ज्ञात हिस्सों के बीच का मान निकालना
GNU grep में -P फ्लैग है, जो Perl-शैली regex देता है। इसमें \K («उससे पहले जो मिला उसे भूल जाओ») और lookahead मिलते हैं, जिनसे सिर्फ़ मान निकाला जा सकता है:
$ echo 'user_id=4821 status=ok' | grep -oP 'user_id=\K[0-9]+'
4821
$ grep -oP '"version":\s*"\K[^"]+' package.json
2.4.1
-P हर grep build में नहीं होता (जैसे macOS के BSD grep में नहीं), इसलिए पोर्टेबल स्क्रिप्ट में sed या awk बेहतर हैं।
स्क्रिप्ट की शर्तों में grep -q
grep -q कुछ नहीं छापता, केवल exit code लौटाता है: 0 मतलब मिला, 1 मतलब नहीं मिला। इसलिए जाँच सीधे if में लिखी जा सकती है:
if grep -q "^PermitRootLogin no" /etc/ssh/sshd_config; then
echo "root-लॉगिन बंद है"
fi
यह आउटपुट को वेरिएबल में रखकर उसके खाली होने की जाँच करने से छोटा है, और grep पहले मिलान पर ही रुक जाता है।
sed: टेक्स्ट बदलना और हटाना
बदलाव: s कमांड
sed की मुख्य कमांड है s/पैटर्न/नया-टेक्स्ट/फ्लैग। g फ्लैग के बिना हर लाइन में केवल पहला मिलान बदलता है।
# बदला हुआ टेक्स्ट दिखाएँ (फ़ाइल नहीं बदलती)
sed 's/foo/bar/' file.txt
# लाइन में सभी मिलान बदलें
sed 's/foo/bar/g' file.txt
# केस को अनदेखा करके (GNU sed)
sed 's/error/ERROR/gI' app.log
# अलग separator, अगर टेक्स्ट में स्लैश हों
sed 's|/var/www|/srv/www|g' nginx.conf
sed -i: फ़ाइल के अंदर बदलाव
-i फ्लैग नतीजा सीधे फ़ाइल में लिख देता है। मूल फ़ाइल न खोएँ, इसके लिए बैकअप का सफ़िक्स दें:
# config.ini.bak बनाएगा और config.ini बदलेगा
sed -i.bak 's/^debug=true/debug=false/' config.ini
# डायरेक्टरी की सभी .conf फ़ाइलों में बदलाव
find /etc/myapp -name "*.conf" -exec sed -i 's/old-host/new-host/g' {} +
बड़े पैमाने पर बदलने से पहले -i के बिना कमांड चलाकर आउटपुट देखें। macOS (BSD sed) में -i के साथ अनिवार्य आर्गुमेंट चाहिए: sed -i '' 's/a/b/' file।
लाइनों को नंबर या पैटर्न से चुनना
# 10 से 20 तक की लाइनें दिखाएँ (-n ऑटो-प्रिंट बंद करता है, p का मतलब प्रिंट)
sed -n '10,20p' file.txt
# 5वीं लाइन हटाएँ
sed '5d' file.txt
# आख़िरी लाइन हटाएँ
sed '$d' file.txt
# खाली लाइनें और टिप्पणियाँ हटाएँ
sed -e '/^$/d' -e '/^#/d' nginx.conf
# केवल उन लाइनों में बदलें जहाँ "listen" है
sed '/listen/s/80/8080/' nginx.conf
# मिलान के बाद नई लाइन जोड़ें (GNU sed)
sed '/^\[mysqld\]/a max_connections = 500' my.cnf
Back-reference और &
पैटर्न के कोष्ठक वाले हिस्से को \1, \2 से नए टेक्स्ट में डाला जा सकता है, और & पूरे मिले हुए टेक्स्ट को दर्शाता है।
# नाम और उपनाम की अदला-बदली (-E से ERE)
$ echo "Sharma Ravi" | sed -E 's/(\S+) (\S+)/\2 \1/'
Ravi Sharma
# सभी संख्याओं को चौकोर कोष्ठक में लपेटें
$ echo "port 8080, timeout 30" | sed -E 's/[0-9]+/[&]/g'
port [8080], timeout [30]
# तारीख 2026-10-14 को 14.10.2026 बनाएँ
$ echo 2026-10-14 | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3.\2.\1/'
14.10.2026
awk: कॉलम, शर्तें और गिनती
ज़रूरी कॉलम निकालना
awk हर लाइन को स्पेस और टैब से फ़ील्ड में बाँटता है: $1 पहला फ़ील्ड, $2 दूसरा, $NF आख़िरी, और $0 पूरी लाइन।
# nginx लॉग से IP पते (पहला कॉलम)
awk '{print $1}' /var/log/nginx/access.log
# /etc/passwd से यूज़रनेम और shell (विभाजक — कोलन)
awk -F: '{print $1, $7}' /etc/passwd
# आख़िरी कॉलम
df -h | awk '{print $NF}'
# आउटपुट में अपना विभाजक
awk -F: -v OFS=';' '{print $1, $3}' /etc/passwd
शर्तें: केवल ज़रूरी लाइनें छापना
ब्लॉक से पहले शर्त रखी जा सकती है, तब awk वह क्रिया केवल सही लाइनों पर करेगा।
# UID 1000 या उससे ऊपर वाले यूज़र (सामान्य, सिस्टम नहीं)
awk -F: '$3 >= 1000 {print $1}' /etc/passwd
# 500 या उससे ऊपर के response code वाले अनुरोध (combined फ़ॉर्मेट में 9वाँ फ़ील्ड)
awk '$9 >= 500' access.log
# जहाँ 6वाँ कॉलम regex से मेल खाए
awk '$6 ~ /POST/' access.log
# ls -l के आउटपुट से 100 MB से बड़ी फ़ाइलें
ls -l | awk '$5 > 100*1024*1024 {print $9}'
BEGIN, END और NR: awk एक छोटे प्रोग्राम की तरह
BEGIN ब्लॉक पहली लाइन पढ़ने से पहले चलता है और END आख़िरी लाइन के बाद। NR मौजूदा लाइन का नंबर रखता है, और END ब्लॉक में कुल लाइनों की संख्या।
# जवाबों का कुल आकार (10वाँ फ़ील्ड) मेगाबाइट में
awk '{sum += $10} END {printf "%.1f MB\n", sum/1024/1024}' access.log
# आख़िरी कॉलम का औसत समय
awk '{s += $NF} END {if (NR) print s/NR}' timings.log
# CSV का हेडर छोड़ें
awk -F, 'NR > 1 {print $2}' users.csv
# IP के अनुसार अनुरोधों की गिनती: associative array
awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log | sort -rn | head
आख़िरी उदाहरण लॉग-विश्लेषण का क्लासिक तरीका है: count array, जिसकी key IP है, sort | uniq -c की जोड़ी की जगह लेता है और आसानी से बढ़ाया जा सकता है, जैसे हर पते के कुल ट्रैफ़िक तक।
Pipeline: grep, sed और awk साथ में
असली ताक़त संयोजन में है। हर टूल अपना हिस्सा करता है और | नतीजा आगे भेजता है।
5xx गलतियों वाले शीर्ष 10 IP
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
यहाँ grep मोटे तौर पर लाइनें छाँटता है, awk फ़ील्ड काटता है, और sort | uniq -c दोहराव गिनता है। यही काम एक awk से भी हो सकता है: awk '$9 ~ /^5/ {c[$1]++} END {for (i in c) print c[i], i}' access.log | sort -rn | head। यह ज़्यादा सटीक है, क्योंकि यहाँ सीधे response code वाला कॉलम जाँचा जाता है।
कौन-से URL सबसे ज़्यादा खुलते हैं
awk '{print $7}' access.log | sed 's/?.*//' | sort | uniq -c | sort -rn | head
यहाँ sed query-string को काट देता है, ताकि /search?q=a और /search?q=b एक ही पेज माने जाएँ।
बिना टिप्पणी वाले config से वेरिएबल के नाम
grep -v '^\s*#' /etc/myapp/app.env | grep '=' | awk -F= '{print $1}'
किसी घंटे की गलतियाँ
grep '14/Oct/2026:03:' access.log | awk '$9 >= 500 {print $4, $7, $9}'
आम गलतियाँ
- awk में डबल कोट की जगह सिंगल कोट।
awk "{print $1}"में shell awk के चलने से पहले अपना$1बदल देता है। awk प्रोग्राम और sed के एक्सप्रेशन सिंगल कोट में लिखें। - sed में
gभूल जाना। इसके बिना लाइन में केवल पहला मिलान बदलता है, बाक़ी वैसे ही रहते हैं। - बिना जाँच के
sed -i। ग़लत regex चुपचाप फ़ाइल ख़राब कर देगा। पहले-iके बिना चलाएँ या-i.bakइस्तेमाल करें। - grep में
+और|काम नहीं करते। यह extended सिंटैक्स है, इसके लिएgrep -E(याsed -E) चाहिए। - पैटर्न में बिंदु।
grep 192.168.1.1192x168y1z1से भी मेल खाएगा, क्योंकि बिंदु का मतलब «कोई भी अक्षर» है।grep -Fइस्तेमाल करें या\.लिखें। - कॉलम में स्पेस। अगर फ़ील्ड में स्पेस हो सकते हैं (CSV, रास्ते), तो विभाजक साफ़ लिखें:
awk -F,याawk -F'\t'। - बेकार cat।
cat file | grep xकाम करता है, परgrep x fileछोटा है और एक अतिरिक्त प्रोसेस नहीं बनाता।
grep, sed और awk की जगह क्या
JSON के लिए ये यूटिलिटी सुविधाजनक नहीं हैं: JSON की संरचना jq से बेहतर पढ़ी जाती है (jq '.items[] | select(.status=="active") | .name'), और YAML के लिए yq। बड़े प्रोजेक्ट में तेज़ रिकर्सिव खोज के लिए अक्सर ripgrep (कमांड rg) इस्तेमाल होता है, जो डिफ़ॉल्ट रूप से .gitignore का ध्यान रखता है। अगर Perl सिंटैक्स पसंद है, तो perl -pe 's/a/b/g' और perl -lane 'print $F[0]' एक लाइन में sed और awk का काम करते हैं। पर grep, sed और awk लगभग हर सर्वर पर बिना इंस्टॉल किए मिल जाते हैं, इसलिए इन्हें पहले सीखना चाहिए।
निष्कर्ष
grep लाइनें खोजता है, sed उन्हें बदलता है, awk कॉलम के साथ काम करता है और गिनती करता है। बुनियादी सेट याद रखें: grep -rniE और -A/-B/-C, sed 's/.../.../g' के साथ -i.bak और -n 'Np', awk -F के साथ $1, $NF, शर्तें और END ब्लॉक। इन्हीं से लगभग हर लॉग-विश्लेषण बनता है। ये grep sed awk उदाहरण, find, jq और curl के साथ, हमारे Linux कोर्स के उस लेक्चर में व्यवहार में समझाए गए हैं जो टर्मिनल में टेक्स्ट प्रोसेसिंग के बारे में है।
अक्सर पूछे जाने वाले प्रश्न
grep और egrep में क्या अंतर है?
egrep पुराना उपनाम है grep -E (extended regular expressions) के लिए। नई GNU grep वर्ज़न egrep चलाने पर चेतावनी देते हैं, इसलिए grep -E लिखें।
डायरेक्टरी की सारी फ़ाइलों में टेक्स्ट कैसे खोजें?
grep -rn "टेक्स्ट" /path इस्तेमाल करें: -r रिकर्सिव खोजता है, -n लाइन नंबर दिखाता है। फ़ाइल प्रकार सीमित करने के लिए --include="*.php" जोड़ें।
कई फ़ाइलों में एक साथ टेक्स्ट कैसे बदलें?
खोज और sed जोड़ें: grep -rl "old" . | xargs sed -i 's/old/new/g'। पहले commit या बैकअप बना लेना बेहतर है।
awk में कई कॉलम tab से अलग करके कैसे छापें?
आउटपुट विभाजक सेट करें: awk -v OFS='\t' '{print $1, $3}' file। OFS के बिना फ़ील्ड के बीच स्पेस आता है।
sed से लाइनों के आख़िर के स्पेस कैसे हटाएँ?
sed -i 's/[[:space:]]*$//' file फ़ाइल की सभी लाइनों के आख़िर से स्पेस और tab हटा देता है।
यह विषय “Linux: с нуля до уверенного администрирования” कोर्स में अभ्यास के साथ विस्तार से समझाया गया है।
कोर्स पर जाएँ