Grep में 'उसके बाद नहीं' के लिए रेगेक्स लुकहेड


103

मैं केवल पत्र के Ui\.बाद Lineया उसके बाद के सभी उदाहरणों के लिए टालमटोल करने का प्रयास कर रहा हूंL

एक विशेष स्ट्रिंग के सभी उदाहरणों को खोजने के लिए एक और स्ट्रिंग के बाद न लिखने के लिए उचित तरीका क्या है?

लुकाहेड्स का उपयोग करना

grep "Ui\.(?!L)" *
bash: !L: event not found


grep "Ui\.(?!(Line))" *
nothing

5
रेगेक्स की कौन-सी उप-प्रजातियाँ हैं - पीसीआरई, ईआरई, बीआरई, जीआरपी, एड, सेड, पर्ल, पायथन, जावा, सी, ...?
जोनाथन लेफ़लर 16

4
एक तरफ के रूप में, "घटना नहीं मिली" इतिहास विस्तार का उपयोग करने से आती है। यदि आप कभी भी इसका उपयोग नहीं करते हैं, और कभी-कभी अपने इंटरैक्टिव कमांड में विस्मय बोधक चिह्न का उपयोग करने में सक्षम होना चाहते हैं, तो आप इतिहास विस्तार को बंद कर सकते हैं। set +o histexpandबैश या set +H, YMMV में।
ट्रिपल

12
मेरे पास इतिहास विस्तार का मुद्दा भी था। मुझे लगता है कि मैंने इसे केवल एकल उद्धरणों पर स्विच करके हल किया है, इसलिए शेल तर्क को मोड़ने की कोशिश नहीं करेगा।
कोडर सेप

@ कोडर जिसने मेरी समस्या को भी हल किया। धन्यवाद।
NHDaly

जवाबों:


151

नकारात्मक लुकहैड, जो आप के बाद है, मानक से अधिक शक्तिशाली उपकरण की आवश्यकता है grep। आपको PCRE- सक्षम grep की आवश्यकता है।

यदि आपके पास जीएनयू है grep, तो वर्तमान संस्करण विकल्पों का समर्थन करता है -Pया --perl-regexpफिर आप फिर से रेक्सक्स का उपयोग कर सकते हैं जो आप चाहते थे।

यदि आपके पास GNU का पर्याप्त (हालिया संस्करण) नहीं है grep, तो प्राप्त करने पर विचार करें ack


37
मुझे पूरा यकीन है कि इस मामले में समस्या बस इतनी है कि आपको बैश में दोहरे उद्धरण चिह्नों का उपयोग नहीं करना चाहिए, इसलिए यह !एक विशेष चरित्र के रूप में नहीं माना जाएगा ।
NHDaly

(ठीक उसी तरह का वर्णन करने के लिए मेरे जवाब के लिए नीचे देखें।)
NHDaly

4
सत्यापित, सही उत्तर इस उत्तर और @ NHDaly की टिप्पणी का संयोजन होना चाहिए। उदाहरण के लिए, यह कमांड मेरे लिए काम करता है: grep -P '^। * समाहित करता है ((?! (!_Not_this))।) * $' * .log। *> "D: \ temp \ result.out"
wangf

3
उन लोगों के लिए जहां -Pसमर्थित नहीं है grep --invert-match, फिर से पाइपिंग परिणाम का प्रयास करें , उदा git log --diff-filter=D --summary | grep -E 'delete.*? src' | grep -E --invert-match 'xml':। @Vinicius Ottoni के उत्तर को सुनिश्चित करें।
डैनियल सोकोलोव्स्की

@ क्वांग के तहत बैश का उपयोग कर रहा हूं और जब मैं सिंगल कोट्स में बदलता हूं, तब भी मुझे "इवेंट नहीं मिला" त्रुटि मिल रही है।
SSilk

40

आपकी समस्या के भाग का उत्तर यहाँ है, और एक ही तरह से व्यवहार करेगा: Ack & negative lookahead त्रुटियाँ दे रहा है

आप grep के लिए दोहरे-उद्धरणों का उपयोग कर रहे हैं, जो " !इतिहास विस्तार कमांड के रूप में व्याख्या करने" के लिए बैश की अनुमति देता है ।

आपको SINGLE-QUOTES में अपना पैटर्न लपेटने की आवश्यकता है: grep 'Ui\.(?!L)' *

हालाँकि, मानक में नकारात्मक लुकहैड्स के साथ मुद्दों को संबोधित करने के लिए @ जोनाथनएलफ्लर का उत्तर देखें grep!


आप grepमानक की कार्यक्षमता के साथ GNU के विस्तार की कार्यक्षमता को भ्रमित कर रहे हैं grep, जहां grepPOSIX के लिए मानक है। आप जो कहते हैं वह भी सच है - मैं बैश को सी-शेल बारबेरिज्म से अक्षम करता हूं (क्योंकि अगर मुझे सी शेल चाहिए था, तो मैं एक का उपयोग करूंगा, लेकिन मुझे एक नहीं चाहिए), इसलिए !सामान मुझे प्रभावित नहीं करता है - लेकिन नकारात्मक रूप-रंग पाने के लिए, आपको गैर-मानक चाहिए grep
जोनाथन लेफ़लर

1
@JonathanLeffler, स्पष्टीकरण के लिए धन्यवाद; मुझे लगता है कि आप सही हैं कि ओपी के सभी लक्षणों को दूर करने के लिए हमारे दोनों उत्तरों की आवश्यकता है। धन्यवाद।
NHDaly

11

आप शायद grep का उपयोग करते हुए मानक नकारात्मक लुकहैड्स नहीं कर सकते, लेकिन आमतौर पर आपको "व्युत्क्रम" स्विच '-v' का उपयोग करके समान व्यवहार प्राप्त करने में सक्षम होना चाहिए। उस का उपयोग करके आप जो मैच करना चाहते हैं उसके पूरक के लिए एक रेगेक्स का निर्माण कर सकते हैं और फिर इसे 2 ग्रेप के माध्यम से पाइप कर सकते हैं।

सवाल में रेगेक्स के लिए आप कुछ ऐसा कर सकते हैं

grep 'Ui\.' * | grep -v 'Ui\.L'

अगर लाइन में Ui.Line और Ui शामिल हैं, तो अधिक चीजें, अधिक उदाहरणों को बाहर कर देगा। Line
nafg

1
(हां, इसलिए मैं इसे कड़ाई से तैयार नहीं करता हूं। यह बस परिदृश्यों के महत्वपूर्ण हिस्से को हल करता है जो लोगों को इस समस्या पर नेविगेट करता है, इससे ज्यादा कुछ नहीं।)
कारेल टूसक

4

यदि आपको एक रेगेक्स कार्यान्वयन का उपयोग करने की आवश्यकता है जो नकारात्मक लुकहेड्स का समर्थन नहीं करता है और आपको अतिरिक्त चरित्र (एस) * से मेल खाने में कोई आपत्ति नहीं है, तो आप नकारात्मक चरित्र वर्गों[^L] , प्रत्यावर्तन| और स्ट्रिंग एंकर$ के अंत का उपयोग कर सकते हैं ।

आपके मामले grep 'Ui\.\([^L]\|$\)' *में काम करता है।

  • Ui\. उस स्ट्रिंग से मेल खाता है जिसमें आप रुचि रखते हैं

  • \([^L]\|$\)के अलावा किसी भी एक चरित्र से Lमेल खाता है या यह रेखा के अंत से मेल खाता है: [^L]या $

यदि आप केवल एक से अधिक वर्णों को बाहर करना चाहते हैं, तो आपको बस उस पर और अधिक प्रत्यावर्तन और नकार को फेंकने की आवश्यकता है। इसके aबाद नहीं खोजने के लिए bc:

grep 'a\(\([^b]\|$\)\|\(b\([^c]\|$\)\)\)' *

जो या तो ( पंक्ति के अंत में aनहीं है bया उसके बाद अनुसरण किया जाता है: या aतो ) या ( जिसके बाद [^b]या तो पंक्ति के अंत में या उसके बाद अनुसरण किया जाता है : फिर , तब या ।$abcab[^c]$

इस तरह की अभिव्यक्ति को बहुत ही कमज़ोर होना पड़ता है और एक छोटी स्ट्रिंग के साथ त्रुटि भी होती है। आप के लिए भाव उत्पन्न करने के लिए आप कुछ लिख सकते हैं, लेकिन यह संभव है कि केवल रेगेक्स कार्यान्वयन का उपयोग करना आसान हो जो नकारात्मक लुकहेड का समर्थन करता है।

* यदि आपका कार्यान्वयन गैर-कैप्चरिंग समूहों का समर्थन करता है तो आप अतिरिक्त वर्णों को कैप्चर करने से बच सकते हैं।


1

यदि आपका grep -P या --perl-regexp का समर्थन नहीं करता है, और आप PCRE- सक्षम grep, उदाहरण के लिए "pcregrep" स्थापित कर सकते हैं, तो इसके लिए पर्ल-संगत नियमित को स्वीकार करने के लिए GNU grep जैसे किसी भी कमांड-लाइन विकल्प की आवश्यकता नहीं होगी। भाव, आप बस चलाते हैं

pcregrep "Ui\.(?!Line)"

आपको अपने उदाहरण "Ui।" (? ((लाइन))) के रूप में "लाइन" के लिए एक और नेस्टेड समूह की आवश्यकता नहीं है - बाहरी समूह पर्याप्त है, जैसे मैंने ऊपर दिखाया है।

मुझे नकारात्मक प्रतिक्रियाओं को देखने का एक और उदाहरण दें: जब आपके पास "ipset" द्वारा लौटी लाइनों की सूची हो, तो प्रत्येक पंक्ति लाइन के बीच में पैकेटों की संख्या दिखाती है, और आपको शून्य पैकेट वाले लाइनों की आवश्यकता नहीं है, आप बस Daud:

ipset list | pcregrep "packets(?! 0 )"

यदि आपको पर्ल-संगत रेगुलर एक्सप्रेशन पसंद हैं और आपके पास perl है, लेकिन pcregrep नहीं है या आपका grep --perl-regexp का समर्थन नहीं करता है, तो आप एक-लाइन perl स्क्रिप्ट का उपयोग कर सकते हैं जो grep की तरह ही काम करती है:

perl -e "while (<>) {if (/Ui\.(?!Lines)/){print;};}"

पर्ल उसी तरह स्टड को स्वीकार करता है जैसे जीआरपी

ipset list | perl -e "while (<>) {if (/packets(?! 0 )/){print;};}"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.