क्या grep के -A -B -C स्विच (कुछ लाइनों को पहले और बाद में प्रिंट करने के लिए) का कोई विकल्प है?


10
grep -A 2 -B 3 

grep स्ट्रिंग के बाद 2 लाइनों को प्रिंट करता है और 3 लाइनों को पहले प्रिंट करता है।

grep -C 3

3 लाइनों से पहले और 3 लाइनों के बाद प्रिंट करता है

दुर्भाग्य से, grepमैं उपयोग कर रहा हूं इन विकल्पों का समर्थन नहीं करता। क्या इसका अनुकरण करने के लिए कोई वैकल्पिक कमांड या स्क्रिप्ट उपलब्ध है? sed/ awk/ perl/ शेल स्क्रिप्ट का उपयोग करना ?


+1 मैं नहीं जानता था कि -Cस्विच था ।
लेज़र

1
GNU का grep स्थापित करें। आम तौर पर, जब एक नया सन मशीन यहां आया, तो सेटअप में पहला कदम किसी को बुलाया गया था GNU > /usr/local। जीएनयू कार्यक्रमों में बहुत उपयोगी एक्सटेंशन हैं, और मनमाने प्रतिबंधों से बचने के लिए डिज़ाइन किए गए हैं (लेकिन आप आकार और कभी-कभी प्रदर्शन में बहुत अधिक भुगतान करते हैं)। कई प्रोपियोरी सिस्टम में जीएनयू और अन्य उपकरणों के साथ "अनौपचारिक" पैकेज रिपॉजिटरी हैं। "पार्टनर" आपको उनके बारे में नहीं बताएगा, भले ही वे वेंडर द्वारा प्रबंधित हों ...
vonbrand

जवाबों:


6

यह करने के लिए एक मामूली बदसूरत तरीका है

grep -v pattern file >file.tmp; diff -c file.tmp file

या बदलने के -cसाथ -C NUMके लिए NUMसंदर्भ की तर्ज। हालांकि यह अतिरिक्त उत्पादन करेगा। (यदि आपका diffसमर्थन करता है -u/ -U NUM, यह क्लीनर होगा।)

यदि आपके diffपास -c/ -C/ नहीं है -u, तो अभी भी इसे करने के तरीके हैं, लेकिन वे बहुत बदसूरत हैं। दूसरी ओर, एक प्रणाली जिसका diffसमर्थन भी नहीं करता है , -cशायद पर्ल के पास भी नहीं है।


यह शांत है, आकर्षण की तरह काम करता है, हालांकि मुझे इसके साथ -bitw विकल्प का उपयोग करना पड़ा, ताकि यह खिड़कियों से उत्पन्न फ़ाइलों के लिए काम कर सके।
प्रशांत भाटे

आप स्टड को अलग करने के लिए भेज सकते हैं, और अस्थायी को छोड़ सकते हैं:grep -v pattern file | diff -c - file
Cascabel

5

एसीके केवल पर्ल आवश्यकता है, और भी शामिल है -A, -Bऔर -Cविकल्प है कि ग्रेप की तरह काम करते हैं। यह grep के बजाय पर्ल के रेगेक्स सिंटैक्स का उपयोग करता है, और जिस तरह से यह खोज करने के लिए फ़ाइलों का चयन करता है वह काफी अलग है। आप -fइसका उपयोग करते समय विकल्प की कोशिश कर सकते हैं (जो फ़ाइलों को प्रिंट करता है वह वास्तव में कुछ भी खोजे बिना खोज करेगा)।

इसे एकल स्क्रिप्ट के रूप में स्थापित किया जा सकता है जिसके लिए बिना कोर मॉड्यूल की आवश्यकता होती है। बस इसे अपनी ~/binनिर्देशिका में (या अपने पेटीएम पर कहीं भी छोड़ दें जिसे आपने लिखा है) और सुनिश्चित करें कि यह chmodनिष्पादन योग्य है।


इसका उत्पादन बॉक्स और दुर्भाग्य से मुझे कुछ भी स्थापित करने का पर्याप्त विशेषाधिकार नहीं है, और मैं इसे जोखिम में नहीं डाल सकता हूं, हालांकि, इस टिप के लिए धन्यवाद मैं इसे स्थापित करूंगा और अपने घर के लैपटॉप पर कोशिश करूंगा
प्रशांत भाटे

@Prashant, आपको ackअपने स्वयं के उपयोग के लिए स्थापित करने के लिए रूट की आवश्यकता नहीं है ।
cjm

हां, लेकिन फिर भी मैं वहां इसका उपयोग नहीं कर सकता, हालांकि यह सुनिश्चित है कि यह स्क्रिप्ट हमेशा मेरे ~ / बिन :) में रहेगी
प्रशांत भाटे

@ प्रशांत: आप इसका उपयोग क्यों नहीं कर सकते? यह सिर्फ एक पर्ल स्क्रिप्ट है।
intuited

1
इसका प्रोडक्शन बॉक्स, इस पर कोई भी बात करने के लिए विशेष अनुमति अनुमोदन ब्ला ब्ला ब्ला ... लेने की आवश्यकता है। और मेरे सिर पर आने से कुछ भी गलत होता है;) और इसके लायक नहीं है :)
प्रशांत भाटे

5

यह सरल पर्ल स्क्रिप्ट grep -Aकुछ हद तक अनुकरण करती है

#!/usr/bin/perl

$pattern=shift; #patthern to search
$lines=shift; # number of lines to print

$n = 0;
while (<>) {
  $n = $lines if /$pattern/; # reset counting
  if ($n) { print; $n-- } # print if within
  $n = 0 if eof; # don't leak across file boundaries
}

ध्यान दें कि स्क्रिप्ट को पठनीय और प्रयोग करने योग्य बनाने के लिए आप एक उपयोग विवरण जोड़ सकते हैं;)

USAGE:    $./grep-A.pl <pattern> <numLines> <filename> 

अच्छा, पर्ल के किस संस्करण को मुझे इसे चलाने की आवश्यकता है?
प्रशांत भाटे 20

मैं v5.10.1 का उपयोग करता हूं, मुझे लगता है कि पर्ल 5 इन दिनों काफी सामान्य है।
विजय अनंत

फिर इसके 5.8.8 और यह काम करता है, बहुत अच्छा, लेकिन मुझे एक स्क्रिप्ट की ज़रूरत है जो कि -B क्या करती है
प्रशांत भाटे

अच्छा। मैं तर्कों का क्रम बदलूँगा, हालाँकि; grep-A 3 fooकी तुलना में बहुत अधिक प्राकृतिक दिखता है grep-A foo 3। :-)
मुशीफिल

3

आप बस GNU grep या Ack स्थापित कर सकते हैं (पर्ल में लिखा गया, GNU grep के कई विकल्पों को समझता है और अधिक)।

यदि आप मानक उपकरण और थोड़ी स्क्रिप्टिंग से चिपके रहना पसंद करते हैं, तो यहां एक अजीब स्क्रिप्ट है जो GNU grep के विकल्पों -Aऔर -Bविकल्पों के व्यवहार का अनुकरण करती है । न्यूनतम परीक्षण किया गया।

#!/bin/sh
# grep-ac: a grep-like awk script
# Arguments: pattern = awk regexp to search for
#            before = number of lines to print before a match
#            after = number of lines to print after a match
{ "exec" "awk" "-f" "$0" "$@"; }
# The array h contains the history of lines that haven't been printed
# but are eligible for being "before" lines.
# The variable until contains the number of the last "after" line to print.
match($0, pattern) {   # the current line matches
    for (i in h) {
        print h[i];    # print each remaining before line
        delete h[i];   # delete each line as it's printed
    }
    until=NR+after;    # record the last after line to print
}
{
    if (NR<=until) print $0;    # from a match to its last after line: print
    else h[NR]=$0;              # after that: save in history
    delete h[NR-before];        # remove line too old to be a before line
}
END {exit !until}               # exit status: 0 if there was a match, else 1

के रूप में यह भागो grep-ac -vpattern=PATTERN -vbefore=NBEFORE -vafter=NAFTERजहां PATTERNपैटर्न (एक के लिए खोज करने के लिए है विस्तारित नियमित अभिव्यक्ति में कुछ के साथ awk अतिरिक्त ), और NBEFOREऔर NAFTERलाइनों की संख्या पहले और एक मैच में क्रमश: (0 करने के लिए दोषी) के बाद मुद्रित करने के लिए कर रहे हैं। उदाहरण:

<input_file grep-ac -vbefore=2 -vpattern='foo *bar'

सरणी में डेटा संग्रहीत करने वाला कोई भी समाधान प्रश्न से बाहर है ... जैसा कि मैंने पहले उल्लेख किया है, फाइल करना काफी विशाल है और यह प्रवाह से अधिक हो सकता है। इसके अलावा इस सिस्टम पर awk फ़ाइल का आकार 3000 से अधिक बाइट्स की अनुमति नहीं देता है।
प्रशांत भाटे

2
@ प्रशांत: मैं आपकी हरकतों को नहीं समझता। यह स्क्रिप्ट लाइनों को हटा देती है जब वे पहले लाइनों के लिए अयोग्य हो जाते हैं। यह आवश्यकताओं को देखते हुए स्वाभाविक रूप से अधिक स्मृति का उपयोग नहीं करता है, सिवाय इसके कि जाग एक विशेष प्रयोजन कार्यक्रम (लेकिन पर्ल से कम है, जिसे आप भी विचार कर रहे हैं) की तुलना में अधिक ओवरहेड हो सकता है। फ़ाइल का कुल आकार पूरी तरह से अप्रासंगिक है।
गिल्स एसओ- बुराई को रोकना '

2
{ "exec" "awk" "-f" "$0" "$@"; }: शेबंग-लाइन पार्सिंग में सीमाओं के आसपास जाने के लिए बहुत ही निफ्टी तरीका है।
डब्यूजिम

2

यह पता चला है कि यह अनुकरण करने के लिए काफी मुश्किल है, क्योंकि उन मुद्दों की वजह से जब आप एक दूसरे के बाद सीधे लाइनों का मिलान करते हैं। यह बहुत ज्यादा किसी भी तरह के सिंगल-पास-थ्रू फ़ाइल स्कैनिंग का उपयोग नहीं करता है।

निम्नलिखित सन्निकटन के साथ खेलने के दौरान मुझे यह एहसास हुआ:

perl -pe 'if(/search_term/) {print foreach @A; print ">"; $B=4}; shift @A if push(@A, $_)>7; $_ = "" unless ($B-- > 0);' target_file

यह लगभग सही ढंग से grep -A7 -B3 के रूप में काम करेगा, पहले पैराग्राफ में वर्णित चेतावनी के साथ।

इस समस्या का एक वैकल्पिक (एकल-फ़ाइल) समाधान, कमांड स्ट्रिंग को सीड फीड करने के लिए पर्ल का उपयोग करना है:

sed -n `perl -pe '$_=(/search_term/?sprintf("%d,%dp;", $.-3,$.+4):"")' file` file

सुंदर lenghty oneliner, लेकिन, यह फ़ाइल बहुत विशाल है, इसलिए इस मामले में सरणी में लाइनों को धक्का देना एक बुरा विचार है, क्या यह नहीं है?
प्रशांत भाटे

shift @A if push(@A,$_)>7;बिट केवल अधिकतम आकार लगभग 7 की एक सरणी रहता है। (यह आपका ए-पैरामीटर है)। दूसरा विकल्प एक अविश्वसनीय रूप से छोटी फ़ाइल को इधर-उधर रखता है (केवल सीड बाहरी परत के बिना पर्ल को देखने के लिए कि वहां क्या उत्पन्न होता है), लेकिन यह फाइल को दो बार पढ़ता है।
user455

0

उपयोग करने से sedआप पहली बार एक whileलूप में दिए गए लाइन नंबर को मिलाते, घटाते और बढ़ाते हैं, और फिर sed -n "n1,n2p"लीडिंग ( n1) और ट्रेलिंग ( n2) संदर्भ ( sedयूजर 455 द्वारा सुझाए गए विकल्प के समान) की लाइनों को प्रिंट करने के लिए उपयोग कर सकते हैं । कई पढ़ने की प्रक्रिया हालांकि एक प्रदर्शन हिट हो सकती है।

edएक मिलान रेखा की पिछली और निम्न पंक्तियों को सीधे संदर्भित कर सकता है, लेकिन यदि निर्दिष्ट रेखा सीमा मौजूद नहीं है, तो विफल हो जाती है; उदाहरण के लिए, मिलान रेखा पंक्ति संख्या 2 है, लेकिन 5 पूर्व-मिलान लाइनें मुद्रित की जानी चाहिए। edइसलिए इसका उपयोग शुरू और अंत में उचित संख्या में (खाली) लाइनों को जोड़ना आवश्यक है। (बड़ी फ़ाइलों के edलिए सही उपकरण नहीं हो सकता है, हालांकि देखें: bfs - बड़ी फ़ाइल स्कैनर )।

# sample code to match lines with number 5 plus previous & following line
# (using Bash)
printf '%s\n' {1..20} > num.txt

# sed
sed -n '/5/=' num.txt | while read num; do
   n1=$((num - 1))
   n2=$((num + 1))
   [[ $n1 -lt 1 ]] && n1=1
   sed -n "${n1},${n2}p" num.txt
   echo --
done | sed -e '${/^--$/d;}'

# ed
cat <<-'EOF' | ed -s num.txt | sed -e $'N;N;a\\\n--' | sed -e '${/^--$/d;}'
H
0i
beginning: added line one
.
$a
end: added line one
.
,g/5/km\
'm-1,'m+1p
q
EOF
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.