ग्रीप में एक गैर-लालची मैच कैसे करें?


177

मैं सबसे छोटा मैच जीतना चाहता हूं और पैटर्न कुछ इस तरह होना चाहिए:

<car ... model=BMW ...>
...
...
...
</car>

... किसी भी चरित्र का मतलब है और इनपुट कई लाइनें हैं।


जवाबों:


276

आप एक गैर-लालची (या आलसी) मैच की तलाश कर रहे हैं। नियमित अभिव्यक्तियों में एक गैर-लालची मैच पाने के लिए आपको ?मात्रा के बाद संशोधक का उपयोग करने की आवश्यकता होती है । उदाहरण के लिए आप बदल सकते हैं .*करने के लिए .*?

डिफ़ॉल्ट रूप से grepगैर-लालची संशोधक का समर्थन नहीं करता है, लेकिन आप grep -Pपर्ल सिंटैक्स का उपयोग कर सकते हैं ।


3
eegg: डॉट सभी संशोधक को मल्टीलाइन के रूप में भी जाना जाता है। यह एक संशोधक है जो "बदलता है।" मैच व्यवहार को शामिल करने के लिए newlines (आमतौर पर यह नहीं है)। Grep में ऐसा कोई संशोधक नहीं है, लेकिन pcregrep में है
ए। विल्सन

1
सुधार: अधिकांश रेगेक्स फ्लेवर्स में जो इसका समर्थन करते हैं, जो मोड नईलाइनों. से मेल खाने की अनुमति देता है उसे डॉटॉल या सिंगल-लाइन मोड कहा जाता है; रूबी ही एकमात्र है जो इसे मल्टीलाइन कहती है । अन्य जायके में, बहुस्तरीय वह मोड है जो एंकर ( ^और $) को लाइन सीमाओं पर मैच करने की अनुमति देता है। रूबी के पास कोई समकक्ष मोड नहीं है क्योंकि रूबी में वे हमेशा उस तरह से काम करते हैं।
एलन मूर

5
-Pमुझ पर एक पूरी तरह से नया था, मैं खुशी से साल के लिए दूर रहा है, और केवल का उपयोग कर -E... इतने साल बर्बाद! - स्वयं पर ध्यान दें: मैन पेजों को (और भी अधिक!) नियमित रूप से पढ़ें, आप कभी भी पर्याप्त स्विच और विकल्प नहीं पचाते।
ओसोडो

29
कुछ प्लेटफार्मों पर (जैसे मैक ओएस एक्स) grepसमर्थन नहीं करता है -P, लेकिन यदि आप उपयोग egrepकरते हैं तो आप .*?उसी परिणाम को प्राप्त करने के लिए पैटर्न का उपयोग कर सकते हैं । egrep -o 'start.*?end' text.html
साल्विनट्स

4
@SaltyNuts टिप्पणी के विस्तार के रूप में, मैक ओएस एक्स समर्थन नहीं करता है, -Pलेकिन -Eकॉल करेगा egrepइसलिए सुझाया गया .*?कार्य ठीक है।
फ्रेड्रिक एरलैंडसन

83

वास्तव में .*?केवल काम करता है perl। मुझे यकीन नहीं है कि समकक्ष grep विस्तारित regexp सिंटैक्स क्या होगा। सौभाग्य से आप grep के साथ perl syntax का उपयोग कर सकते हैं इसलिए grep -Pकाम करेगा लेकिन grep -Eजो egrepकाम नहीं करेगा (यह लालची होगा)।

इसे भी देखें: http://blog.vinceliu.com/2008/02/non-greedy- अनियमित-expression-matching.html


9
grep -PGNU grep 2.9 में काम नहीं करता है - बस इसे आज़माया (इसमें कोई त्रुटि नहीं है, बस चुपचाप इसे लागू नहीं करता है ?। अंत में न तो वर्ग नहीं करता है जैसे:env|grep '[^\=]*\='
roberto tomás

2
डार्विन / ओएस एक्स 10.8 माउंटेन लायन में कोई grep -Pविकल्प या pgrepआदेश नहीं है , लेकिन egrepमहान काम करता है।
स्टीव एचएचएच

2
pgrepमेरे OS X 10.9 बॉक्स पर एक कमांड है, लेकिन यह एक पूरी तरह से अलग कार्यक्रम है जिसका उद्देश्य "नाम से प्रक्रिया या संकेत प्राप्त करना" है।
डेथ

@ robertotomás ने यहां 6 साल पुरानी टिप्पणी का जवाब दिया, लेकिन .... मैंने भी यही सोचा और फिर महसूस किया कि मुझे कई गैर-लालची मैच मिल रहे हैं। उदाहरण के लिए, एक रंग टर्मिनल पर आप देख सकते हैं कि 'इको "bbbbb" | grep -P 'b। *? b'` 2 मैच लौटाता है।
zzxyz

12

मेरा धागा जो इस धागे में सामान बाहर निकालने के बाद काम करता है:

echo "hi how are you " | grep -shoP ".*? "

बस यह सुनिश्चित करें कि आप अपनी प्रत्येक पंक्ति में एक स्थान जोड़ लें

(मेरा शब्दों को बाहर निकालने के लिए लाइन सर्च द्वारा एक लाइन थी)


3
-shoPअच्छा स्मरक :)
मारिउज़

echo "bbbbb" | grep -shoP 'b.*?b'सीखने का एक छोटा सा अनुभव है। केवल स्पष्ट रूप से आलसी के रूप में मेरे लिए काम करने वाली चीज।
zzxyz

12

grep

गैर-लालची मैच के लिए grepआप एक नकारात्मक चरित्र वर्ग का उपयोग कर सकते हैं। दूसरे शब्दों में, वाइल्डकार्ड से बचने की कोशिश करें।

उदाहरण के लिए, पृष्ठ सामग्री से jpeg फ़ाइलों के लिए सभी लिंक लाने के लिए, आप उपयोग करेंगे:

grep -o '"[^" ]\+.jpg"'

मल्टीपल लाइन से निपटने के लिए, xargsपहले इनपुट को पाइप से करें । प्रदर्शन के लिए, का उपयोग करें ripgrep


3

संक्षिप्त उत्तर अगली नियमित अभिव्यक्ति का उपयोग कर रहा है:

(?s)<car .*? model=BMW .*?>.*?</car>
  • (? s) - यह मल्टीलाइन में एक मेल बनाता है
  • । *? - किसी भी चरित्र से मेल खाता है, आलसी तरीके से कई बार (न्यूनतम मैच)

A (थोड़ा) अधिक जटिल उत्तर है:

(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>

यह निम्नलिखित पाठ में car1 और car2 से मेल करना संभव बनाता है

<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>
  • (..) एक कैप्चरिंग ग्रुप का प्रतिनिधित्व करता है
  • इस सन्दर्भ में \ 1 सममिति से मेल खाता है जैसा कि हाल ही में समूह संख्या 1 पर कब्जा करके मेल खाता है

1

क्षमा करें, मुझे 9 साल की देरी हो गई है, लेकिन यह 2020 में दर्शकों के लिए काम कर सकता है।

तो मान लीजिए आपके पास एक लाइन है जैसे "Hello my name is Jello"। अब आप उन शब्दों को ढूंढना चाहते हैं जो बीच में से किसी भी वर्ण के साथ शुरू 'H'और समाप्त होते हैं 'o'। और हम उन पंक्तियों को नहीं चाहते जिन्हें हम केवल शब्द चाहते हैं। तो इसके लिए हम अभिव्यक्ति का उपयोग कर सकते हैं:

grep "H[^ ]*o" file

इससे सभी शब्द वापस आ जाएंगे। जिस तरह से यह काम करता है वह है: यह बीच के अंतरिक्ष वर्ण के बजाय सभी वर्णों को अनुमति देगा, इस तरह हम एक ही पंक्ति में कई शब्दों से बच सकते हैं।

अब आप अंतरिक्ष चरित्र को अपने इच्छित किसी अन्य चरित्र से बदल सकते हैं। मान लें कि प्रारंभिक लाइन थी "Hello-my-name-is-Jello", तो आप अभिव्यक्ति का उपयोग करके शब्द प्राप्त कर सकते हैं:

grep "H[^-]*o" file

0

मुझे पता है कि यह एक मृत पोस्ट का एक सा है, लेकिन मैंने अभी देखा कि यह काम करता है। इसने मेरे आउटपुट से क्लीन-अप और क्लीनअप दोनों को हटा दिया।

> grep -v -e 'clean\-\?up'
> grep --version grep (GNU grep) 2.20
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.