नियमित भावों के संदर्भ में 'आलसी' और 'लालची' का क्या अर्थ है?


जवाबों:


643

लालची जितना संभव हो उतना उपभोग करेगा। Http ://www . अनियमित-expressions.info/repeat.html से हम HTML टैग के साथ मिलान करने के प्रयास का उदाहरण देखते हैं <.+>। मान लें कि आपके पास निम्नलिखित हैं:

<em>Hello World</em>

आप सोच सकते हैं कि <.+>( .साधन किसी भी गैर न्यू लाइन चरित्र और +साधन एक या अधिक ) केवल मेल खाएगा <em>और </em>, जब वास्तविकता में यह बहुत लालची हो जाएगा, और पहले से जाना <पिछले करने के लिए >। इसका मतलब यह है कि यह <em>Hello World</em>आप क्या चाहते थे के बजाय मैच होगा ।

इसे आलसी ( <.+?>) बनाने से रोका जा सकेगा। ?बाद में जोड़कर +, हम इसे कम से कम कई बार दोहराने के लिए कहते हैं , इसलिए पहले> आता है, जहां हम मिलान रोकना चाहते हैं।

मैं आपको RegExr को डाउनलोड करने के लिए प्रोत्साहित करता हूं , एक महान उपकरण जो आपको नियमित अभिव्यक्ति का पता लगाने में मदद करेगा - मैं इसका हर समय उपयोग करता हूं।


2
इसलिए यदि आप लालची का उपयोग करेंगे तो आपके पास 3 (1 तत्व + 2 टैग) मैच या सिर्फ 1 मैच (1 तत्व) होगा?
अज़ीसी

10
यह केवल 1 बार मेल खाता है, पहले < से शुरू होता है और अंतिम > के साथ समाप्त होता है ।
सैम्पसन

3
लेकिन इसे आलसी बनाने से दो बार मेल होगा, हमें उद्घाटन और समापन दोनों टैग देगा, बीच में पाठ को अनदेखा करना (क्योंकि यह अभिव्यक्ति को फिट नहीं करता है)।
सैम्पसन

एक और महान उपकरण जिसका मैं हमेशा उपयोग करता हूं: debuggex.com इसमें एक "एंबेड ऑन स्टैकऑवरफ्लो " फ़ंक्शन भी है।
रॉन वान डेर हाइजेन

8
बस जोड़ने के लिए कि इसके बारे में जाने के लिए एक लालची तरीका है, भी: <[^>]+> regex101.com/r/lW0cY6/1
alanbuchanan

301

'लालची' का अर्थ है सबसे लंबे समय तक संभव स्ट्रिंग से मेल खाना।

'आलसी' का अर्थ है कम से कम संभव स्ट्रिंग का मिलान करें।

उदाहरण के लिए, लालची h.+lमेल खाता 'hell'है 'hello'लेकिन आलसी h.+?lमेल खाता है 'hel'


96
शानदार, इसलिए आलसी बंद हो जाएगा जैसे ही शर्त l संतुष्ट है, लेकिन लालची का मतलब है कि यह केवल तभी बंद हो जाएगा जब शर्त l कोई संतुष्ट नहीं है?
एंड्रयू एस

3
पोस्ट पढ़ने वाले सभी लोगों के लिए: लालची या आलसी क्वांटिफायर अपने आप में सबसे लंबे / कम से कम संभव विकल्प से मेल नहीं खाते। आपको या तो टेम्पर्ड लालची टोकन का उपयोग करना होगा , या गैर-रेगेक्स दृष्टिकोण का उपयोग करना होगा।
विकटोरिया स्ट्राइब्यू

3
@AndrewS उदाहरण में डबल ll द्वारा भ्रमित न हों। यह बल्कि आलसी सबसे कम संभव विकल्प से मेल खाएगा, जबकि लालची सबसे लंबे समय तक संभव होगा। लालची h.+lमेल खाता 'helol'है 'helolo'लेकिन आलसी h.+?lमेल खाता है 'hel'
v.shashenko

3
@FloatingRock: सं का x?मतलब xवैकल्पिक है लेकिन +?एक अलग वाक्यविन्यास है। इसका मतलब है कि आप कुछ ऐसा ढूंढना बंद कर दें, जो मेल खाता हो - आलसी मिलान।
स्लीपबेटमैन

1
@FloatingRock: जैसा कि आप विभिन्न वाक्यविन्यास को अलग करते हैं, सरल: ?वैकल्पिक का +?मतलब है और आलसी का मतलब है। इसलिए \+?साधन +वैकल्पिक है।
स्लीपबेटमैन

113
+-------------------+-----------------+------------------------------+
| Greedy quantifier | Lazy quantifier |        Description           |
+-------------------+-----------------+------------------------------+
| *                 | *?              | Star Quantifier: 0 or more   |
| +                 | +?              | Plus Quantifier: 1 or more   |
| ?                 | ??              | Optional Quantifier: 0 or 1  |
| {n}               | {n}?            | Quantifier: exactly n        |
| {n,}              | {n,}?           | Quantifier: n or more        |
| {n,m}             | {n,m}?          | Quantifier: between n and m  |
+-------------------+-----------------+------------------------------+

एक जोड़ें ? एक मात्रा के लिए यह अस्वाभाविक यानी आलसी बनाने के लिए।

उदाहरण:
परीक्षण स्ट्रिंग: stackoverflow
लालची reg अभिव्यक्ति : s.*oउत्पादन: stackoverflo डब्ल्यू
आलसी reg अभिव्यक्ति : s.*?oउत्पादन: stacko verflow


2
नहीं है ?? के बराबर ? । इसी तरह, {n} नहीं है? {n} के समतुल्य
नंबर 945

5
@BreakingBenjamin: नहीं ?? के बराबर नहीं है?, जब यह 0 या 1 घटना को वापस करने का विकल्प होता है, तो यह 0 (आलसी) विकल्प चुन लेगा। अंतर देखने के लिए, तुलना re.match('(f)?(.*)', 'food').groups()करें re.match('(f)??(.*)', 'food').groups()। उत्तरार्द्ध में, (f)??अग्रणी 'f' से मेल नहीं खाएगा, भले ही यह हो सकता है। इसलिए 'f' दूसरे '' से मेल खाएगा। * '' कैप्चर ग्रुप। मुझे यकीन है कि आप '{n}?' के साथ एक उदाहरण बना सकते हैं। भी। माना जाता है कि इन दोनों का उपयोग बहुत कम ही किया जाता है।
smci

55

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

abcdefghijklmc

और यह अभिव्यक्ति:

a.*c

एक लालची मैच पूरे स्ट्रिंग से मेल खाएगा, और एक आलसी मैच बस पहले से मेल खाएगा abc


16

जहां तक ​​मुझे पता है, अधिकांश रेगेक्स इंजन डिफ़ॉल्ट रूप से लालची होता है। क्वांटिफायर के अंत में एक प्रश्न चिह्न जोड़ें आलसी मैच को सक्षम करेगा।

जैसा कि @Andre S ने टिप्पणी में उल्लेख किया है।

  • लालची: जब तक स्थिति संतुष्ट न हो, खोज जारी रखें।
  • आलसी: एक बार हालत संतुष्ट होने पर खोजना बंद करें।

लालची क्या है और आलसी क्या है, इसके लिए नीचे दिए गए उदाहरण का संदर्भ लें।

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    public static void main(String args[]){
        String money = "100000000999";
        String greedyRegex = "100(0*)";
        Pattern pattern = Pattern.compile(greedyRegex);
        Matcher matcher = pattern.matcher(money);
        while(matcher.find()){
            System.out.println("I'm greeedy and I want " + matcher.group() + " dollars. This is the most I can get.");
        }

        String lazyRegex = "100(0*?)";
        pattern = Pattern.compile(lazyRegex);
        matcher = pattern.matcher(money);
        while(matcher.find()){
            System.out.println("I'm too lazy to get so much money, only " + matcher.group() + " dollars is enough for me");
        }
    }
}


परिणाम है:

I'm greeedy and I want 100000000 dollars. This is the most I can get.

I'm too lazy to get so much money, only 100 dollars is enough for me

9

Www . अनियमित-expressions.info से लिया गया

लालच : लालची परिमाणकों पहले की कोशिश करता संभव के रूप में कई बार के रूप टोकन को दोहराने के लिए, और धीरे धीरे एक समग्र मैच खोजने के लिए इंजन backtracks के रूप में मैचों देता है।

आलस्य : आलसी क्वांटिफायर पहले आवश्यकता के अनुसार टोकन को कई बार दोहराता है, और धीरे-धीरे मैच को विस्तार देता है क्योंकि इंजन रेगेक्स के माध्यम से समग्र मैच ढूंढता है।


6

से नियमित अभिव्यक्ति

नियमित अभिव्यक्तियों में मानक क्वांटिफायर लालची होते हैं, जिसका अर्थ है कि वे जितना संभव हो उतना मैच करते हैं, केवल शेष रेगेक्स से मिलान करने के लिए आवश्यक है।

एक आलसी क्वांटिफायर का उपयोग करके, अभिव्यक्ति पहले न्यूनतम मैच की कोशिश करती है।


4

लालची मिलान। नियमित अभिव्यक्तियों का डिफ़ॉल्ट व्यवहार लालची होना है। इसका मतलब है कि यह यथासंभव संभव निकालने की कोशिश करता है जब तक कि यह एक पैटर्न के अनुरूप नहीं होता है जब एक छोटा सा हिस्सा वाक्यविन्यास रूप से पर्याप्त होता।

उदाहरण:

import re
text = "<body>Regex Greedy Matching Example </body>"
re.findall('<.*>', text)
#> ['<body>Regex Greedy Matching Example </body>']

'>' की पहली घटना तक मिलान के बजाय, इसने पूरी स्ट्रिंग निकाली। यह डिफ़ॉल्ट लालची है या रेगेक्स का 'यह सब' व्यवहार है।

दूसरी ओर, आलसी मिलान , 'जितना संभव हो उतना कम होता है।' यह ?पैटर्न के अंत में जोड़कर प्रभावित किया जा सकता है ।

उदाहरण:

re.findall('<.*?>', text)
#> ['<body>', '</body>']

यदि आप चाहते हैं कि केवल पहला मैच फिर से प्राप्त किया जाए, तो इसके बजाय खोज विधि का उपयोग करें।

re.search('<.*?>', text).group()
#> '<body>'

स्रोत: पायथन रेगेक्स उदाहरण


3

लालची का मतलब है कि यह आपके पैटर्न का उपभोग करेगा जब तक कि उनमें से कोई भी नहीं बचा है और यह आगे नहीं देख सकता है।

जैसे ही आप अनुरोध किए गए पहले पैटर्न का सामना करेंगे, आलसी रुक जाएगा।

एक आम उदाहरण है कि मेरा अक्सर सामना \s*-\s*?एक रेगेक्स से होता है([0-9]{2}\s*-\s*?[0-9]{7})

पहले \s*को लालची के रूप में वर्गीकृत किया *गया है और अंकों का सामना करने के बाद जितना संभव हो सके उतने सफेद रिक्त स्थान देखेंगे और फिर एक डैश चरित्र "-" की तलाश करेंगे। जहां के रूप में दूसरा \s*?आलसी है क्योंकि वर्तमान का *?अर्थ है कि यह पहले सफेद अंतरिक्ष चरित्र को देखेगा और वहीं रुक जाएगा।


3

सबसे अच्छा उदाहरण के द्वारा दिखाया गया है। स्ट्रिंग। 192.168.1.1और एक लालची रेगेक्स \b.+\b आपको लगता है कि यह आपको 1 ऑक्टेट देगा लेकिन वास्तव में पूरे स्ट्रिंग के खिलाफ मैच है। क्यों? क्योंकि। + लालची है और एक लालची मैच हर चरित्र से मेल खाता है 192.168.1.1जब तक कि यह स्ट्रिंग के अंत तक नहीं पहुंचता है। यह महत्वपूर्ण बिट है! अब यह एक समय में एक चरित्र को पीछे करना शुरू कर देता है जब तक कि यह 3 जी टोकन ( \b) के लिए एक मैच नहीं पाता है ।

यदि स्ट्रिंग एक 4GB पाठ फ़ाइल और 192.168.1.1 शुरुआत में थी, तो आप आसानी से देख सकते हैं कि यह बैकट्रैकिंग कैसे समस्या का कारण बनेगी।

एक रेगेक्स नॉन लालची (आलसी) बनाने के लिए अपने लालची खोज उदा के बाद एक प्रश्न चिह्न लगाएं

*?
??
+?

अब क्या होता है टोकन 2 ( +?) एक मैच पाता है, रेगेक्स एक चरित्र के साथ चलता है और फिर \b2 टोकन ( ) के बजाय अगले टोकन की कोशिश करता है +?। तो यह अदरक के साथ रेंगता है।


0

लालची क्वांटिफायर्स आईआरएस / एटीओ की तरह हैं: वे उतना ही लेते हैं जितना वे ले सकते हैं:

अगर यह वहाँ है, तो वे आएंगे और इसे ले जाएंगे। वे इसे ले लेंगे:

उदाहरण के लिए, आईआरएस इस रेगेक्स के साथ मेल खाता है: .*

$50,000 - आईआरएस यह सब ले जाएगा। उन लालची .*{4}?ओरों को

एक उदाहरण के लिए यहाँ देखें: regexr.com/4t27f

गैर-लालची क्वांटिफायर - वे जितना हो सके उतना कम लेते हैं

दूसरी ओर, यदि मैं एक कर वापसी के लिए कहता हूं, तो आईआरएस अचानक गैर-लालची हो जाता है, और वे इस मात्रा का उपयोग करते हैं:

(.{2}?)([0-9]*)इस अभिव्यक्ति के खिलाफ: $50,000पहला समूह गैर-जरूरतमंद है और केवल मेल खाता है $5- इसलिए मुझे ए$5 रिफंड । बाकी को चाचा सैम ने व्यर्थ खर्च करने के लिए लिया है।

यहाँ देखें: गैर लालची-उदाहरण

क्यों परेशान?

यह महत्वपूर्ण हो जाता है यदि आप एक अभिव्यक्ति के कुछ हिस्सों से मेल खाने की कोशिश कर रहे हैं। कभी-कभी आप सब कुछ मैच नहीं करना चाहते हैं।


-3

निम्नलिखित व्यवहार को समझने की कोशिश करें:

    var input = "0014.2";

Regex r1 = new Regex("\\d+.{0,1}\\d+");
Regex r2 = new Regex("\\d*.{0,1}\\d*");

Console.WriteLine(r1.Match(input).Value); // "0014.2"
Console.WriteLine(r2.Match(input).Value); // "0014.2"

input = " 0014.2";

Console.WriteLine(r1.Match(input).Value); // "0014.2"
Console.WriteLine(r2.Match(input).Value); // " 0014"

input = "  0014.2";

Console.WriteLine(r1.Match(input).Value); // "0014.2"
Console.WriteLine(r2.Match(input).Value); // ""
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.