गाइड

grep, sed और awk: टर्मिनल में टेक्स्ट प्रोसेसिंग के उदाहरण

अपडेट किया गया: · Skillaria.Top

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 में लिखते हैं, इसलिए इन्हें | से आसानी से जोड़ा जा सकता है। फ़र्क इस बात में है कि कौन-सा काम कौन सबसे अच्छा करता है।

कामटूलउदाहरण
टेक्स्ट वाली लाइनें खोजनाgrepgrep ERROR app.log
टेक्स्ट बदलनाsedsed 's/http:/https:/g' file
नंबर से लाइनें हटाना या दिखानाsedsed -n '10,20p' file
कोई कॉलम निकालनाawkawk '{print $1}' access.log
जोड़, औसत, समूह बनानाawkawk '{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.1 192x168y1z1 से भी मेल खाएगा, क्योंकि बिंदु का मतलब «कोई भी अक्षर» है। 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: с нуля до уверенного администрирования” कोर्स में अभ्यास के साथ विस्तार से समझाया गया है।

कोर्स पर जाएँ