एक फ़ाइल में एक पैटर्न की घटनाओं की संख्या (यहां तक ​​कि एक ही पंक्ति पर)


94

जब एक फ़ाइल में एक स्ट्रिंग की घटनाओं की संख्या के लिए खोज, मैं आमतौर पर उपयोग करें:

grep pattern file | wc -l

हालाँकि, यह केवल प्रति पंक्ति एक घटना को खोजता है, क्योंकि जिस तरह से grep काम करता है। मैं एक फ़ाइल में एक स्ट्रिंग दिखाई देने की संख्या के लिए कितनी बार खोज सकता हूं, चाहे वे एक ही या अलग-अलग लाइनों पर हों?

इसके अलावा, क्या होगा अगर मैं एक रेगेक्स पैटर्न की तलाश कर रहा हूं, एक साधारण स्ट्रिंग नहीं? मैं उन लोगों को कैसे गिन सकता हूं, या और भी बेहतर, प्रत्येक मैच को एक नई लाइन पर प्रिंट कर सकता हूं।

जवाबों:


156

सभी घटनाओं को गिनने के लिए, उपयोग करें -o। इसे इस्तेमाल करे:

echo afoobarfoobar | grep -o foo | wc -l

और man grepनिश्चित रूप से:

अपडेट करें

कुछ grep -co fooइसके बजाय सिर्फ उपयोग करने का सुझाव देते हैं grep -o foo | wc -l

मत करो।

यह शॉर्टकट सभी मामलों में काम नहीं करेगा। मैन पेज कहता है:

-c print a count of matching lines

इन दृष्टिकोणों में अंतर नीचे दिया गया है:

1।

$ echo afoobarfoobar | grep -oc foo
1

जैसे ही मैच लाइन ( a{foo}barfoobar) में मिलता है सर्च रुक जाता है। केवल एक लाइन की जाँच की गई थी और यह मेल खाता था, इसलिए आउटपुट है 1। वास्तव -oमें यहां नजरअंदाज किया गया है और आप grep -cइसके बजाय इस्तेमाल कर सकते हैं ।

2।

$ echo afoobarfoobar | grep -o foo
foo
foo

$ echo afoobarfoobar | grep -o foo | wc -l
2

दो मैच लाइन में पाए जाते हैं ( a{foo}bar{foo}bar) क्योंकि हमने स्पष्ट रूप से हर घटना को खोजने के लिए कहा है ( -o)। प्रत्येक घटना एक अलग लाइन पर मुद्रित होती है, और wc -lआउटपुट में लाइनों की संख्या की गणना करती है।


1
वाह ... क्या यह वास्तव में इतना आसान है?
जर्दोको

1
grep -oc इस मामले में काम नहीं करता है। इको अफोबारफोबर को आजमाएं | grep -oc फू
पॉलस

क्या कई फ़ाइलों के लिए ऐसा करने का कोई तरीका नहीं है? मान लीजिए कि मैं फ़ाइलों के एक सेट पर प्रति फ़ाइल आवृत्तियों की संख्या देखना चाहता हूं। मैं इसे grep -c * के साथ प्रति पंक्ति कर सकता हूं , लेकिन प्रति उदाहरण नहीं।
कीथ टायलर

grep -o foo a.txt b.txt | sort | uniq -cठीक काम करता है (GNU grep के साथ): gist.github.com/hudolejev/81a05791f38cbacfd4de3ee3b44eb4f8
hudolejev

2

इसे इस्तेमाल करे:

grep "string to search for" FileNameToSearch | cut -d ":" -f 4 | sort -n | uniq -c

नमूना:

grep "SMTP connect from unknown" maillog | cut -d ":" -f 4 | sort -n | uniq -c
  6  SMTP connect from unknown [188.190.118.90]
 54  SMTP connect from unknown [62.193.131.114]
  3  SMTP connect from unknown [91.222.51.253]

1

एक बेल्ड पोस्ट:
इसमें सर्च रेपेक्स पैटर्न को रिकॉर्ड सेपरेटर (RS) के रूप में प्रयोग करें, awk
यह आपके रेगेक्स को \n-delimited लाइनों (यदि आपको इसकी आवश्यकता है) की अनुमति देता है ।

printf 'X \n moo X\n XX\n' | 
   awk -vRS='X[^X]*X' 'END{print (NR<2?0:NR-1)}'

0

Ripgrep , जो grep का एक तेज़ विकल्प है, ने अभी --count-matchesध्वज को संस्करण 0.9 में प्रत्येक मैच की गणना करने की अनुमति दी है (मैं लगातार रहने के लिए उपरोक्त उदाहरण का उपयोग कर रहा हूं):

> echo afoobarfoobar | rg --count foo
1
> echo afoobarfoobar | rg --count-matches foo
2

ओपी द्वारा पूछे जाने पर, रिपग्रेप रेगेक्स पैटर्न के लिए भी अनुमति देता है ( --regexp <PATTERN>)। इसके अलावा यह प्रत्येक (लाइन) मैच को एक अलग लाइन पर प्रिंट कर सकता है:

> echo -e "line1foo\nline2afoobarfoobar" | rg foo
line1foo
line2afoobarfoobar

-1

हैक grep के रंग समारोह, और गिनती कितने रंग टैग यह प्रिंट:

echo -e "a\nb  b b\nc\ndef\nb e brb\nr" \
| GREP_COLOR="033" grep --color=always  b \
| perl -e 'undef $/; $_=<>; s/\n//g; s/\x1b\x5b\x30\x33\x33/\n/g; print $_' \
| wc -l
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.