2012-10-14 15 views
9

इस regexयह रेगेक्स लालची क्यों नहीं है?

$line = 'this is a regular expression'; 
$line =~ s/^(\w+)\b(.*)\b(\w+)$/$3 $2 $1/; 

print $line; 

में $ 2 " is a regular " के बराबर क्यों है? मेरी विचार प्रक्रिया यह है कि (। *) लालची होनी चाहिए और रेखा के अंत तक सभी पात्रों से मेल खाना चाहिए और इसलिए $ 3 खाली होगा।

हालांकि ऐसा नहीं हो रहा है। रेगेक्स मैचर किसी भी तरह अंतिम शब्द सीमा से ठीक पहले रोक रहा है और आखिरी शब्द सीमा के बाद $ 3 को पॉप्युलेट कर रहा है और बाकी स्ट्रिंग को $ 2 तक भेजा गया है।

कोई स्पष्टीकरण? धन्यवाद।

उत्तर

15

$3 इस रेगेक्स का उपयोग करते समय खाली नहीं हो सकता है क्योंकि संबंधित कैप्चरिंग समूह (\w+) है, जो कम से कम एक शब्द वर्ण से मेल खाना चाहिए या पूरा मिलान विफल हो जाएगा।

तो क्या होता है (.*) मैच "is a regular expression", \b स्ट्रिंग के अंत से मेल खाता है, और (\w+) मिलान करने के लिए विफल रहता है। regex इंजन तो (.*) मिलान "is a regular " (ध्यान दें मैच अंतरिक्ष भी शामिल है), \be से पहले शब्द सीमा से मेल खाता है, और (\w+) मैच" expression "।

आप (\w+)(\w*) करने के लिए बदल देता है तो आपके साथ खत्म हो जाएगा करने के लिए backtracks परिणाम आप की उम्मीद है, जहां (.*) पूरी स्ट्रिंग खपत करता है।

+0

'' $ एक शून्य चौड़ाई दावा है; मुझे कुछ भी खपत नहीं लगता है (यदि यह संभव है तो) स्ट्रिंग का अंत एक मुद्दा होगा। देखें: http://codepad.org/CwTlhn3z – NullUserException

+0

@NullUserException मैंने इतना सोचा लेकिन [^ (\ w +) \ b (। *) \ B (\ w *) $] (http://rubular.com/r/XczcfFd2Va) अभी भी अंतिम समूह में 'अभिव्यक्ति' से मेल खाता है। जैसा कि मैंने अपेक्षा की थी, शब्द को वैकल्पिक परिणामों को एक खाली मैच में बनाना। मुझे सच में यकीन नहीं है कि वास्तव में क्या चल रहा है ... – verdesmarald

+0

ऐसा लगता है कि रुबी का रेगेक्स इंजन पर्ल से अलग है। – NullUserException

6

लालची यह बिल्कुल सब कुछ मैच के लिए हो जाता है मतलब यह नहीं है। यह सिर्फ यह संभव जितना ले जा सकते हैं और अभी भी regex सफल होने की है का मतलब है।

इसका मतलब है कि चूंकि आप समूह 3 में + का उपयोग करते हैं, यह खाली नहीं हो सकता है और अभी भी + का अर्थ है 1 या अधिक

यदि आप 3 खाली होना चाहते हैं, तो बस (\w+) से (\w?) बदलें। अब ? का अर्थ है 0 या 1 यह खाली हो सकता है, और इसलिए लालची .* सबकुछ लेता है। नोट: यह केवल पर्ल में काम करता है, इस कारण कि लाइनें लाइनों से कैसे निपटती हैं।

+0

का उपयोग करें http://rubular.com/r/1XFcnXANWJ, हालांकि पर्ल में यह वर्णन करता है जैसा कि आपने वर्णन किया है। पर्ल में एक शब्द सीमा स्ट्रिंग का अंत है? – NullUserException

+0

'(\ w?)' मतलब 0, या 1. '(\ w *) 'का अर्थ 0 या उससे अधिक है। –

+0

@BradGilbert यह एक समस्या है? – NullUserException

1

रेगेक्स को पूरे स्ट्रिंग से मिलान करने के लिए, ^(\w+)\b की आवश्यकता है कि पूरा पहला शब्द \1 हो। इसी तरह, \b(\w+)$ की आवश्यकता है कि पूरा अंतिम शब्द \3 हो। इसलिए, कोई फर्क नहीं पड़ता कि कैसे लालची (.*) है, यह केवल 'नियमित है' पर कब्जा कर सकता है, अन्यथा पैटर्न मेल नहीं खाएगा। स्ट्रिंग से मेल खाने के दौरान, .* शायद पूरे 'नियमित अभिव्यक्ति है' ले लिया, लेकिन फिर पाया कि उसे पीछे हटना पड़ा और \w+ को भी अपना मिलान प्राप्त करना पड़ा।

0

जिस तरीके से आपने अपना regexp लिखा है, इससे कोई फर्क नहीं पड़ता कि .* लालची या गैर लालची है। यह अभी भी मेल खाता है।

कारण यह है कि आपने .* और \w+ के बीच उपयोग किया था।

use strict; 
use warnings; 

my $string = 'this is a regular expression'; 

sub test{ 
    my($match,$desc) = @_; 
    print '# ', $desc, "\n" if $desc; 
    print "test(qr'$match');\n"; 
    if(my @elem = $string =~ $match){ 
    print ' 'x4,'[\'', join("']['",@elem), "']\n\n" 
    }else{ 
    print ' 'x4,"FAIL\n\n"; 
    } 
} 

test(qr'^ (\w+) \b (.*) \b (\w+) $'x, 'original'); 
test(qr'^ (\w+) \b (.*+) \b (\w+) $'x, 'extra-greedy'); 
test(qr'^ (\w+) \b (.*?) \b (\w+) $'x, 'non-greedy'); 
test(qr'^ (\w+) \b (.*) \b (\w*) $'x, '\w* instead of \w+'); 
test(qr'^ (\w+) \b (.*)  (\w+) $'x, 'no \b'); 
test(qr'^ (\w+) \b (.*?) (\w+) $'x, 'no \b, non-greedy .*?'); 
# original 
test(qr'(?^x:^ (\w+) \b (.*) \b (\w+) $)'); 
    ['this'][' is a regular ']['expression'] 

# extra-greedy 
test(qr'(?^x:^ (\w+) \b (.*+) \b (\w+) $)'); 
    FAIL 

# non-greedy 
test(qr'(?^x:^ (\w+) \b (.*?) \b (\w+) $)'); 
    ['this'][' is a regular ']['expression'] 

# \w* instead of \w+ 
test(qr'(?^x:^ (\w+) \b (.*) \b (\w*) $)'); 
    ['this'][' is a regular expression'][''] 

# no \b 
test(qr'(?^x:^ (\w+) \b (.*)  (\w+) $)'); 
    ['this'][' is a regular expressio']['n'] 

# no \b, non-greedy .*? 
test(qr'(?^x:^ (\w+) \b (.*?) (\w+) $)'); 
    ['this'][' is a regular ']['expression'] 
+0

मुझे यकीन नहीं है कि उत्तर सवाल ... –

+0

यह मूल regex में विभिन्न मामूली संशोधन दिखाता है। –

संबंधित मुद्दे