कैसे या क्यों `। * का उपयोग कर?` `से बेहतर है। *`


9

मैंने इस सवाल का जवाब दिया SuperUser पर जो कि आउटपुट को ग्रिप करते समय उपयोग किए जाने वाले रेगुलर एक्सप्रेशन से संबंधित था।

मैंने जो उत्तर दिया वह यह था:

 tail -f log | grep "some_string.*some_string"

और फिर, मेरे जवाब में तीन टिप्पणियों में @ @ ने यह लिखा:

.*लालची है और जितना आप चाहते हैं उससे अधिक पर कब्जा कर सकते हैं। .*?आमतौर पर बेहतर है।

फिर यह,

?एक संशोधक है *, यह लालची डिफ़ॉल्ट के बजाय आलसी बना रही है। पीसीआरई मान रहा है।

मैं के लिए googled PCRE, लेकिन मेरे जवाब में इसका क्या महत्व है यह नहीं मिल सका?

और अंत में यह,

मुझे यह भी इंगित करना चाहिए कि यह regex है (डिफ़ॉल्ट रूप से POSIX regex कर रहा है), शेल गोला नहीं।

मुझे केवल यह पता है कि एक Regex क्या है और grep कमांड में इसका बहुत बुनियादी उपयोग है। इसलिए, मुझे उन 3 टिप्पणियों में से कोई भी नहीं मिला और मेरे मन में ये सवाल हैं:

  • .*?बनाम के उपयोग में क्या अंतर हैं .*?
  • जो बेहतर है और किस परिस्थिति में है? कृपया उदाहरण दें।

इसके अलावा टिप्पणियों को समझने में मदद मिलेगी, अगर कोई भी कर सकता है


UPDATE: सवाल के जवाब के रूप में Regex Shell Globs से कैसे अलग हैं? @ कुसलानंद ने अपनी टिप्पणी में यह लिंक प्रदान किया ।

नोट: यदि आवश्यक हो, तो संदर्भ के संदर्भ में उत्तर देने से पहले कृपया इस प्रश्न का उत्तर पढ़ें ।


यह दो बहुत अलग सवाल हैं। पहले प्रश्न का उत्तर unix.stackexchange.com/questions/57957/… द्वारा दिया गया है, जबकि दूसरा प्रश्न पैटर्न के आवेदन पर निर्भर है (इसे सभी परिस्थितियों में "बेहतर" नहीं कहा जा सकता है)।
Kusalananda

आप इस सवाल को केवल बनाम मुद्दे के बारे में संपादित कर सकते हैं । "नियमित अभिव्यक्तियों और शेल ग्लब्स के बीच का अंतर" प्रश्न इस साइट पर पहले ही संबोधित किया जा चुका है। .*.*?
Kusalananda

जवाबों:


7

अशोक पहले ही बताया के बीच का अंतर .*और .*?, तो मैं बस कुछ अतिरिक्त जानकारी प्रदान करेंगे।

grep (GNU संस्करण मानकर) तार से मेल खाने के 4 तरीकों का समर्थन करता है:

  • निश्चित तार
  • बुनियादी नियमित अभिव्यक्ति (BRE)
  • विस्तारित नियमित भाव (ERE)
  • पर्ल-संगत नियमित अभिव्यक्ति (PCRE)

grep डिफ़ॉल्ट रूप से BRE का उपयोग करता है।

BRE और ERE को POSIX के रेगुलर एक्सप्रेशंस चैप्टर में और पीसीआरई को इसकी आधिकारिक वेबसाइट में प्रलेखित किया गया है । कृपया ध्यान दें कि सुविधाओं और वाक्यविन्यास कार्यान्वयन के बीच भिन्न हो सकते हैं।

यह की कीमत कह रही है कि न तो BRE है और न ही ERE समर्थन lazyness :

कई आसन्न दोहराव प्रतीकों ('+', '*', '?', और अंतराल) के व्यवहार से अपरिभाषित परिणाम उत्पन्न होते हैं।

इसलिए यदि आप उस सुविधा का उपयोग करना चाहते हैं, तो आपको इसके बजाय PCRE का उपयोग करना होगा:

# BRE greedy
$ grep -o 'c.*s' <<< 'can cats eat plants?'
can cats eat plants

# BRE lazy
$ grep -o 'c.*\?s' <<< 'can cats eat plants?'
can cats eat plants

# ERE greedy
$ grep -E -o 'c.*s' <<< 'can cats eat plants?'
can cats eat plants

# ERE lazy
$ grep -E -o 'c.*?s' <<< 'can cats eat plants?'
can cats eat plants

# PCRE greedy
$ grep -P -o 'c.*s' <<< 'can cats eat plants?'
can cats eat plants

# PCRE lazy
$ grep -P -o 'c.*?s' <<< 'can cats eat plants?'
can cats

संपादित करें 1

आप कृपया .*बनाम के बारे में थोड़ा समझा सकते हैं .*??

  • .*" संभव सबसे लंबे समय तक" 1 पैटर्न से मेल खाने के लिए उपयोग किया जाता है।

  • .*?"सबसे कम संभव " 1 पैटर्न से मेल खाने के लिए उपयोग किया जाता है।

मेरे अनुभव में, सबसे अधिक वांछित व्यवहार आमतौर पर दूसरा होता है।

उदाहरण के लिए, मान लें कि हमारे पास निम्नलिखित स्ट्रिंग हैं और हम केवल html टैग 2 से मेल खाना चाहते हैं , न कि उनके बीच की सामग्री:

<title>My webpage title</title>

अब .*बनाम की तुलना करें .*?:

# Greedy
$ grep -P -o '<.*>' <<< '<title>My webpage title</title>'
<title>My webpage title</title>

# Lazy
$ grep -P -o '<.*?>' <<< '<title>My webpage title</title>'
<title>
</title>

1. रेगेक्स संदर्भ में "सबसे लंबा" और "सबसे छोटा" का अर्थ थोड़ा मुश्किल है, जैसा कि कुसलानंद ने बताया । अधिक जानकारी के लिए आधिकारिक दस्तावेज देखें।
2. यह html को रेगेक्स के साथ पार्स करने के लिए अनुशंसित नहीं है । यह शैक्षिक उद्देश्यों के लिए केवल एक उदाहरण है, इसका उपयोग उत्पादन में न करें।


आप कृपया .*बनाम के बारे में थोड़ा समझा सकते हैं .*??
C0deDaedalus

@ C0deDaedalus अपडेट किया गया।
nxnev

9

मान लीजिए कि मैं एक स्ट्रिंग लेता हूं जैसे:

can cats eat plants?

लालची का उपयोग c.*sपूरे स्ट्रिंग से मेल खाएगा क्योंकि यह शुरू होता है cऔर इसके साथ समाप्त होता है s, लालची ऑपरेटर होने के नाते यह तब तक मेल खाता रहता है जब तक कि एस की अंतिम घटना नहीं होती।

जबकि आलसी का उपयोग c.*?sकेवल तब तक मेल खाएगा जब तक कि पहली घटना नहीं sमिलती है, अर्थात स्ट्रिंग can cats

उपरोक्त उदाहरण से, आप इसे इकट्ठा करने में सक्षम हो सकते हैं:

"लालची" का अर्थ है सबसे लंबे समय तक संभव स्ट्रिंग का मिलान। "आलसी" का अर्थ है कम से कम संभव स्ट्रिंग का मिलान। एक जोड़ा जा रहा है ?की तरह एक परिमाणक को *, +, ?, या {n,m}बनाता है यह आलसी।


1
"सबसे कम संभव" होगा cats, इसलिए यह उस अर्थ में "सबसे कम संभव" कड़ाई से लागू नहीं कर रहा है।
Kusalananda

2
@ कुसलानंद सच, इस अर्थ में कड़ाई से नहीं, लेकिन यहां "सबसे कम संभव" का अर्थ है सी और एस दोनों की पहली घटना के बीच।
अशोक अरोड़ा

1

एक स्ट्रिंग को कई तरीकों से मिलान किया जा सकता है (सरल से अधिक जटिल तक):

  1. एक स्थिर स्ट्रिंग के रूप में (मान लीजिए var = 'हैलो वर्ल्ड!'):

    [ "$var" = "Hello World!" ] && echo yes
    echo "$var" | grep -F "Hello"
    grep -F "Hello" <<<"$var"

  2. एक ग्लोब के रूप में:

    echo ./* # pwd में सभी फाइलों को सूचीबद्ध करें।
    case $var in (*Worl*) echo yes;; (*) echo no;; esac
    [[ "$var" == *"Worl"* ]] && echo yes

    मूल और विस्तारित ग्लब्स हैं। caseउदाहरण के बुनियादी globs का उपयोग करें। बैश [[उदाहरण विस्तारित ग्लब्स का उपयोग करते हैं। पहला फाइल मैच बेसिक हो सकता है या extglobबैश में सेटिंग जैसे कुछ शेल पर बढ़ाया जा सकता है । इस मामले में दोनों समान हैं। ग्रेप ग्लब्स का इस्तेमाल नहीं कर सकता था।

    ग्लोब में तारांकन का अर्थ है रेगेक्स में तारांकन चिह्न की तुलना में कुछ अलग :

    * matches any number (including none) ofकोई भी वर्ण
    * matches any number (including none) of theपूर्ववर्ती तत्व

  3. मूल नियमित अभिव्यक्ति (BRE) के रूप में:

    echo "$var" | sed 's/W.*d//' # प्रिंट: नमस्कार!
    grep -o 'W.*d' <<<"$var" # प्रिंट वर्ल्ड!

    कोई (मूल) गोले या awk में BRE नहीं हैं।

  4. विस्तारित नियमित भाव (ERE):

    [[ "$var" =~ (H.*l) ]] # मैच: हैलो वर्ल
    echo "$var" | sed -E 's/(d|o)//g' # प्रिंट: नरक गलत!
    awk '/W.*d/{print $1}' <<<"$var" # प्रिंट: नमस्कार
    grep -oE 'H.*l' <<<"$var" # प्रिंट: नमस्ते वर्ल

  5. पर्ल संगत नियमित अभिव्यक्तियाँ:

    grep -oP 'H.*?l # प्रिंट: हेल

केवल एक पीसीआरई *?में कुछ विशिष्ट वाक्यविन्यास अर्थ होते हैं।
यह तारांकन को आलसी (लालची) बनाता है: लालच के बजाय आलस्य

$ grep -oP 'e.*l' <<<"$var"
ello Worl

$ grep -oP 'e.*?l' <<<"$var"
el

यह सिर्फ हिमशैल की नोक है, लालची, आलसी , और विनम्र या कब्जे वाले हैंलुकहैड और लुकबाइंड भी हैं, लेकिन वे तारांकन पर लागू नहीं होते हैं *

गैर-लालची रेगेक्स के समान प्रभाव प्राप्त करने के लिए एक विकल्प है:

$ grep -o 'e[^o]*o' <<<"$var"
ello

विचार बहुत सरल है: एक डॉट का उपयोग न करें ., मैच के लिए अगले वर्ण को नकारें [^o]। एक वेब टैग के साथ:

$ grep -o '<[^>]*>' <<<'<script type="text/javascript">document.write(5 + 6);</script>'
<script type="text/javascript">
</script>

उपरोक्त सभी @ 3 टिप्पणियों को पूरी तरह से स्पष्ट करना चाहिए। टीका:

  • ए। * एक सामान्य रेगेक्स है, एक ग्लोब नहीं है।
  • केवल एक रेगीक्स पीसीआरई संगत हो सकता है।
  • पीसीआरई में: ए संशोधित * परिमाणक। .*लालची .*?नहीं है।

प्रशन

  • के उपयोग में क्या अंतर हैं। ? बनाम। ?

    • A .*?केवल PCRE सिंटैक्स में मान्य है।
    • A .*अधिक पोर्टेबल है।
    • एक गैर-लालची मैच के रूप में एक ही प्रभाव डॉट को एक नकारात्मक चरित्र सीमा के साथ प्रतिस्थापित करके किया जा सकता है: [^a]*
  • जो बेहतर है और किस परिस्थिति में है? कृपया उदाहरण दें।
    बेहतर? यह लक्ष्य पर निर्भर करता है। कोई बेहतर नहीं है, प्रत्येक अलग-अलग उद्देश्यों के लिए उपयोगी है। मैंने ऊपर कई उदाहरण दिए हैं। क्या आपको इससे अधिक चाहिए?

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