पाइप चरित्र वाले पैटर्न के साथ मैं कई पैटर्न के लिए कैसे तैयार हो सकता हूं?


623

मैं कई फाइलों में सभी लाइनों को खोजना चाहता हूं जो दो पैटर्न में से एक से मेल खाती हैं। मैंने उन पैटर्नों को खोजने की कोशिश की, जिन्हें मैं टाइप करके देख रहा हूँ

grep (foo|bar) *.txt

लेकिन शेल |एक पाइप के रूप में व्याख्या करता है और जब barनिष्पादन योग्य नहीं होता है तो शिकायत करता है।

मैं फ़ाइलों के एक ही सेट में कई पैटर्न के लिए grep कैसे कर सकता हूं?



grep 'word1 \ | word2 \ | word3' / path / to / file
lambodar

जवाबों:


861

सबसे पहले, आपको शेल द्वारा विस्तार से पैटर्न की रक्षा करने की आवश्यकता है। ऐसा करने का सबसे आसान तरीका है कि इसके चारों ओर सिंगल कोट्स लगाए जाएं। एकल उद्धरण उन दोनों के बीच (बैकस्लैश सहित) के विस्तार को रोकते हैं; केवल एक चीज जो आप नहीं कर सकते, वह है पैटर्न में सिंगल कोट्स।

grep 'foo*' *.txt

यदि आपको किसी एकल उद्धरण की आवश्यकता है, तो आप इसे '\''(अंत स्ट्रिंग शाब्दिक, शाब्दिक उद्धरण, खुली स्ट्रिंग शाब्दिक) के रूप में लिख सकते हैं ।

grep 'foo*'\''bar' *.txt

दूसरा, grep पैटर्न के लिए दो सिंटैक्स का समर्थन करता है। पुराना, डिफ़ॉल्ट सिंटैक्स ( मूल नियमित अभिव्यक्ति ) वैकल्पिक ( |) ऑपरेटर का समर्थन नहीं करता है , हालांकि कुछ संस्करणों में यह एक एक्सटेंशन के रूप में है, लेकिन बैकस्लैश के साथ लिखा गया है।

grep 'foo\|bar' *.txt

पोर्टेबल तरीका नए सिंटैक्स, विस्तारित नियमित अभिव्यक्तियों का उपयोग करना है । आपको इसे चुनने के लिए -Eविकल्प को पास करना grepहोगा। लिनक्स पर, आप egrepइसके बजाय grep -E(अन्य यूनियनों पर, आप इसे एक उपनाम बना सकते हैं) टाइप कर सकते हैं।

grep -E 'foo|bar' *.txt

दूसरी संभावना यह है कि जब आप किसी भी कई पैटर्न की तलाश कर रहे हों (जैसा कि एक जटिल पैटर्न के निर्माण के विरोध में) तो कई पैटर्न को पास करना है grep। आप -eविकल्प के साथ प्रत्येक पैटर्न से पहले यह कर सकते हैं ।

grep -e foo -e bar *.txt

18
एक विचार के रूप में - जब पैटर्न तय हो जाते हैं, तो आपको वास्तव में आदत में शामिल होना चाहिए fgrepया grep -Fछोटे पैटर्न के लिए, अंतर नगण्य होगा, लेकिन जैसे-जैसे वे लंबे होते जाएंगे, लाभ दिखाई देने लगते हैं ...
TC1

7

18
@ TC1 क्या grep -Fवास्तविक प्रदर्शन लाभ grep कार्यान्वयन पर निर्भर करता है: उनमें से कुछ वैसे भी एक ही एल्गोरिथ्म को लागू करते हैं, ताकि -Fपैटर्न को पार्स करने में लगने वाले समय पर ही फर्क पड़े और न कि समय की खोज में। -Fउदाहरण के लिए, GNU grep अधिक तेज़ नहीं है (इसमें एक बग भी है जो grep -Fमल्टीबाइट स्थानों में धीमी गति से बनाता है - grepवास्तव में उसी के साथ एक ही निरंतर पैटर्न काफी तेज है!)। दूसरी ओर बिजीबॉक्स ग्रीप -Fबड़ी फाइलों पर काफी फायदा पहुंचाता है ।
गिल्स

4
शायद यह उल्लेख किया जाना चाहिए कि अधिक जटिल पैटर्न के लिए जहां वैकल्पिक केवल नियमित अभिव्यक्ति के एक हिस्से के लिए होना है, इसे "\" (और "\") के साथ समूहीकृत किया जा सकता है (बचना डिफ़ॉल्ट "मूल नियमित अभिव्यक्ति" के लिए है) ) (;)।
पीटर मोर्टेनसेन

4
ध्यान दें कि egrepभविष्यवाणी करता है grep -E। यह जीएनयू विशिष्ट नहीं है (इसका निश्चित रूप से लिनक्स से कोई लेना-देना नहीं है)। वास्तव में, आप अभी भी सोलारिस जैसे सिस्टम पाएंगे जहां डिफ़ॉल्ट grepअभी भी समर्थन नहीं करता है -E
स्टीफन चेज़लस

89
egrep "foo|bar" *.txt

या

grep "foo\|bar" *.txt
grep -E "foo|bar" *.txt

चुनिंदा तौर पर gnu-grep के मैन पेज का हवाला देते हुए:

   -E, --extended-regexp
          Interpret PATTERN as an extended regular expression (ERE, see below).  (-E is specified by POSIX.)

Matching Control
   -e PATTERN, --regexp=PATTERN
          Use PATTERN as the pattern.  This can be used to specify multiple search patterns, or to protect  a  pattern
          beginning with a hyphen (-).  (-e is specified by POSIX.)

(...)

   grep understands two different versions of regular expression syntax: basic and extended.”  In  GNU grep,  there
   is  no  difference  in  available  functionality  using  either  syntax.   In  other implementations, basic regular
   expressions are less powerful.  The following description applies to extended regular expressions; differences  for
   basic regular expressions are summarized afterwards.

शुरुआत में मैंने आगे नहीं पढ़ा, इसलिए मैंने सूक्ष्म अंतरों को नहीं पहचाना:

Basic vs Extended Regular Expressions
   In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead  use  the
   backslashed versions \?, \+, \{, \|, \(, and \).

मैंने हमेशा egrep और अनावश्यक रूप से parens का उपयोग किया, क्योंकि मैंने उदाहरणों से सीखा। अब मैंने कुछ नया सीखा। :)


22

TC1 ने कहा, जैसा -Fलगता है प्रयोग करने योग्य विकल्प:

$> cat text
some text
foo
another text
bar
end of file

$> patterns="foo
bar" 

$> grep -F "${patterns}" text
foo
bar

1
@poige मैं $ 'फू \ nbar' विकल्प के बारे में नहीं जानता था, यह सुनिश्चित नहीं करता है कि यहां विस्तार कैसे काम करता है, ऊपर देखने की जरूरत है, लेकिन धन्यवाद, यह वास्तव में उपयोगी है।
haridsv

अच्छा! यह विकल्प भी इसे बहुत तेज चलाने के लिए लगता है (क्योंकि यह रेगेक्स को निष्क्रिय करता है)।
क्वर्टीजगुई

15

सबसे पहले, आपको विशेष वर्णों के लिए उद्धरण का उपयोग करने की आवश्यकता है। दूसरा, यहां तक ​​कि, grepवैकल्पिक रूप से सीधे समझ में नहीं आएगा; आपको उपयोग करने की आवश्यकता होगी egrep, या ( grepकेवल जीएनयू के साथ ) grep -E

egrep 'foo|bar' *.txt

(जब तक कि प्रत्यावर्तन एक बड़े रेगेक्स का हिस्सा न हो, कोष्ठक अनावश्यक होते हैं।)


4
वास्तव में, grep -Eकी तुलना में अधिक मानक है egrep
jw013

8

यदि आपको नियमित अभिव्यक्तियों की आवश्यकता नहीं है, तो यह उपयोग करने के लिए fgrepया grep -Fएकाधिक -e मापदंडों के साथ बहुत तेज़ है , जैसे:

fgrep -efoo -ebar *.txt

fgrep(वैकल्पिक रूप से grep -F) नियमित grep की तुलना में बहुत तेज़ है क्योंकि यह नियमित अभिव्यक्तियों के बजाय निश्चित तारों की खोज करता है।


4
कृपया इस पृष्ठ पर उन टिप्पणियों का भी उल्लेख करें जिन्हें fgrepअपदस्थ किया गया है।
phk

6

आप परिणाम प्राप्त करने के लिए नीचे दिए गए आदेश को आजमा सकते हैं:

egrep 'rose.*lotus|lotus.*rose' some_file

3

एक सस्ता और हंसमुख तरीका है कई पैटर्न के लिए grep:

$ echo "foo" > ewq ; echo "bar" >> ewq ; grep -H -f ewq *.txt ; rm ewq

यह एक स्पष्टीकरण से लाभान्वित हो सकता है।
पीटर मोर्टेंसन

2
स्पष्टीकरण यह है कि grep का -fविकल्प कई पैटर्न वाली फ़ाइल लेता है। एक अस्थायी फ़ाइल बनाने के बजाय (जिसे आप बाद में हटाना भूल सकते हैं), बस शेल की प्रक्रिया प्रतिस्थापन का उपयोग करें:grep -f <(echo foo; echo bar) *.txt
जकोब

3

पाइप ( |) एक विशेष शेल वर्ण है, इसलिए इसे या तो बचना होगा ( \|) या मैनुअल के अनुसार उद्धृत किया जाना चाहिए ( man bash):

कोटिंग का उपयोग शेल के कुछ वर्णों या शब्दों के विशेष अर्थ को निकालने के लिए किया जाता है। इसका उपयोग विशेष वर्णों के लिए विशेष उपचार को अक्षम करने के लिए किया जा सकता है, ताकि आरक्षित शब्दों को इस तरह से पहचाना जा सके और पैरामीटर विस्तार को रोका जा सके।

दोहरे उद्धरण चिह्नों में संलग्न वर्ण, उद्धरणों के भीतर सभी वर्णों के शाब्दिक मूल्य को बनाए रखते हैं

एक गैर-उद्धृत बैकस्लैश ( \) भागने का पात्र है।

देखें: बैश में किन किरदारों से बचना चाहिए?

यहां कुछ उदाहरण दिए गए हैं (अभी तक उल्लेखित उपकरणों का उपयोग नहीं):

  • का उपयोग कर ripgrep:

    • rg "foo|bar" *.txt
    • rg -e foo -e bar *.txt
  • का उपयोग कर git grep:

    • git grep --no-index -e foo --or -e bar

      नोट: यह बूलियन अभिव्यक्तियों का भी समर्थन करता है जैसे --and, --orऔर --not

प्रति पंक्ति AND ऑपरेशन के लिए, देखें: कई और पैटर्न के साथ grep कैसे चलाएं?

प्रति फ़ाइल AND AND के लिए, देखें: एक फ़ाइल में मौजूद कई स्ट्रिंग्स या regexes को कैसे जांचें?


3

मेरे पास पहुंच लॉग थे जहां तारीखों को मूर्खतापूर्ण रूप से प्रारूपित किया गया था: [30 / जून / 2013: 08: 00: 45 +0200]

लेकिन मुझे इसे प्रदर्शित करने की आवश्यकता थी: 30 / जून / 2013 08:00:45

समस्या यह है कि मेरे grep स्टेटमेंट में "OR" का उपयोग करते हुए, मुझे दो मैच एक्सप्रेशन दो अलग-अलग लाइनों पर प्राप्त हो रहे थे।

यहाँ समाधान है:

grep -in myURL_of_interest  *access.log  | \
grep -Eo '(\b[[:digit:]]{2}/[[:upper:]][[:lower:]]{2}/[[:digit:]]{4}|[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}\b)'   \
| paste - - -d" " > MyAccess.log

2

TL; DR: यदि आप एक से अधिक पैटर्न से मेल खाने के बाद और चीजें करना चाहते हैं, तो उन्हें इनक्लूड करें \(pattern1\|pattern2\)

उदाहरण: मैं उन सभी स्थानों को खोजना चाहता हूँ जहाँ एक चर जिसमें 'तारीख' नाम होता है, को एक स्ट्रिंग या इंट के रूप में परिभाषित किया गया है। (उदाहरण के लिए, "int cronDate =" या "स्ट्रिंग टेक्स्टफ़ॉर्मेटडेडस्टेटस्टैंप ="):

cat myfile | grep '\(int\|String\) [a-zA-Z_]*date[a-zA-Z_]* =' 

इसके साथ grep -E, आपको कोष्ठक या पाइप से बचने की आवश्यकता नहीं है, अर्थातgrep -E '(int|String) [a-zA-Z_]*date[a-zA-Z_]* ='


1

यह मेरे लिए काम करता है

root@gateway:/home/sshuser# aws ec2 describe-instances --instance-ids i-2db0459d |grep 'STATE\|TAG'

**STATE**   80      stopped

**STATE**REASON     Client.UserInitiatedShutdown    Client.UserInitiatedShutdown: User initiated shutdown

**TAGS**    Name    Magento-Testing root@gateway:/home/sshuser#

1

ऐसा करने के कई तरीके हैं।

  1. grep 'foo\|bar' *.txt
  2. egrep 'foo|bar' *.txt
  3. find . -maxdepth 1 -type f -name "*.txt" | xargs grep 'foo\|bar'
  4. find . -maxdepth 1 -type f -name "*.txt" | xargs egrep 'foo|bar'

तीसरा और चौथा विकल्प केवल फाइलों में होगा और निर्देशिकाओं .txtको उनके नाम से बचने से बचाना होगा ।
इसलिए, अपने उपयोग-मामले के अनुसार, आप ऊपर वर्णित किसी भी विकल्प का उपयोग कर सकते हैं।
धन्यवाद!!


0

@ geekosaur के जवाब में जोड़ने के लिए , यदि आपके पास कई पैटर्न हैं जिनमें टैब और स्थान भी शामिल हैं, तो आप निम्न कमांड का उपयोग करते हैं

grep -E "foo[[:blank:]]|bar[[:blank:]]"

जहां [[:blank:]]आरई वर्ण वर्ग है जो या तो एक अंतरिक्ष या एक टैब चरित्र का प्रतिनिधित्व करता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.