2012-04-18 15 views
5

सभी रेगेक्स मिलान चर को साफ़/रीसेट करने का सबसे अच्छा तरीका क्या है?रेगेक्स मिलान चर को साफ़ करने का सबसे अच्छा तरीका क्या है?

  • उदाहरण कैसे $1 regex संचालन के बीच रीसेट और का उपयोग करता है नहीं कर रहा है हाल ही में मैच:

    $_="this is the man that made the new year rumble"; 
    /(is) /; 
    /(isnt) /; 
    say $1;   # outputs "is" 
    
  • उदाहरण है कि कैसे इस समस्या पैदा करने वाले जब छोरों के साथ काम हो सकता है:

    foreach (...){ 
        /($some_value)/; 
        &doSomething($1) if $1; 
    } 
    

अद्यतन: मुझे नहीं लगता था कि मुझे ऐसा करने की आवश्यकता होगी, लेकिन उदाहरण -2 केवल एक उदाहरण है। यह प्रश्न मिलान चर को रीसेट करने के बारे में है, न कि उन्हें लागू करने का सबसे अच्छा तरीका।

भले ही, मेरी कोडिंग शैली स्पष्ट और आई-ब्लॉक का उपयोग करने के साथ अधिक इनलाइन थी। इस (उदाहरण 2) पर वापस आने के बाद, कोड की कई पंक्तियों को पढ़ने में यह बहुत संक्षिप्त है, मुझे यह वाक्यविन्यास समझने के लिए तेज़ी से मिल जाएगा।

+7

यह प्रश्न भी है "अगर मुझे खुद को शूट करना है, तो मुझे किस उद्देश्य का लक्ष्य रखना चाहिए?" –

+0

@briandfoy: बिल्कुल :) - ओस्कोन के लिए शेड्यूल देखा, जो आपके प्रेसी को देखने के लिए उत्सुक था। फिर। मुझे लगता है कि लोग सोच रहे हैं कि मुझे समझ में नहीं आता कि 'if (//) 'क्या करता है और इसका उपयोग क्यों किया जाना चाहिए। अक्सर, जब मैं यहां पर हूं तो ऐसा इसलिए होता है क्योंकि किसी और ने नहीं किया और मैं उनके कोड से सबसे आसान तरीका ढूंढ रहा हूं। इस मामले में, मेरा जवाब केवल यही है जो मैंने पूछे गए प्रश्न का उत्तर दिया। * सुधार: मेरा और ikegami *। – vol7ron

+1

तो फिर आप इसे इस तरह क्यों नहीं पूछते? परिस्थितियों की व्याख्या कभी-कभी अच्छे प्रश्नों में बेवकूफ सवाल बनाती है। –

उत्तर

14

रेगेक्स कैप्चर * एक सफल मैच द्वारा रीसेट कर रहे हैं। रेगेक्स कैप्चर को रीसेट करने के लिए, कोई एक छोटा मिलान ऑपरेशन का उपयोग करेगा जो मिलान करने की गारंटी देता है।

"a" =~ /a/; # Reset captures to undef. 

हाँ, यह अजीब लग रहा है, लेकिन आपने कुछ अजीब कुछ करने को कहा।

आप अपने कोड को ठीक हैं, तो आप अजीब दिखने workarounds जरूरत नहीं है। अपने कोड को ठीक करने से भी एक बग पता चलता है!

सुधार:

$_ = "this is the man that made the new year rumble"; 
if (/ (is)/||/(isnt) /) { 
    say $1; 
} else{ 
    ... # You're currently printing something random. 
} 

और

for (...) { 
    if (/($some_pattern)/) { 
     do_something($1); 
    } 
} 

* — Backrefs regex पैटर्न है कि पहले कब्जा कर लिया पाठ से मेल कर रहे हैं। जैसे \1, \k<foo>। आप वास्तव में "रेगेक्स कैप्चर बफर" के बारे में बात कर रहे हैं।

+0

यदि मैं कर सकता था, तो मैं आपको सही करने के लिए आपको डबल अंक दूंगा। हालांकि, दस्तावेज़ इसे "मिलान करने वाले चर" कहते हैं;) – vol7ron

+0

एकमात्र जगह जिसे मैं "मिलान करने वाले चर" देखता हूं [perlrequick] (http://perldoc.perl.org/perlrequick.html) और [perlretut] (http://perldoc.perl.org/perlretut.html)। –

+0

@brian d foy, मुझे "मिलान चर" यह perlre में दिखाई देता है (जो "मिलान चर" से अधिक समझ में आता है), लेकिन मैं वास्तव में शब्द को नापसंद करता हूं। अगर व्यर्थ नहीं है तो यह संदिग्ध है। "कैप्चर बफर" प्रलेखन में कम से कम उपयोग किया जाता है (कम से कम perlre और perlvar में)। तकनीकी रूप से केवल $ 1' कैप्चर बफर होने के बजाय "कैप्चर बफर तक पहुंच की अनुमति देता है", लेकिन यह बाल विभाजित है। – ikegami

17

आपको समूह के युद्धों की स्थिति नहीं, मैच से वापसी का उपयोग करना चाहिए।

foreach (...) { 
    doSomething($1) if /($some_value)/; 
} 

$ 1, आदि केवल मैच के सफल होने पर सबसे हालिया मैच को प्रतिबिंबित करने की गारंटी है। सफल मैच के बाद आपको उन्हें सही से नहीं देखना चाहिए।

+0

आप बिंदु खो रहे हैं। यह एक उदाहरण था (केवल आंशिक कोड)। सवाल बैकरेफर को रीसेट करने के बारे में है। – vol7ron

+12

बड़ा मुद्दा यह है कि आपको कुछ भी नहीं करना चाहिए जो बैकरेफर को रीसेट करने पर निर्भर करता है। यह आपके द्वारा पोस्ट किए गए कोड में उस निर्भरता से बचने का एक उदाहरण था; यदि आपके पास एक अलग उदाहरण है, तो कृपया इसे पोस्ट करें ताकि हम दिखा सकें कि वहां से कैसे बचें। एक सफल मैच के तुरंत बाद किसी भी संदर्भ में $ 1 की सामग्री पर निर्भर एक बग है। अवधि। –

+3

@ vol7ron संख्या यह बिल्कुल स्पॉट और दस्तावेज व्यवहार पर है। [perlvar] (http://perldoc.perl.org/perlvar.html#Variables-related-to-regular-expressions) –

5

आपको परीक्षण करना चाहिए कि मैच सफल हुआ है या नहीं। उदाहरण के लिए:

foreach (...){ 
    /($some_value)/ or next; 
    doSomething($1) if $1; 
} 

foreach (...){ 
    doSomething($1) if /($some_value)/ and $1; 
} 

foreach (...){ 
    if (/($some_value)/) { 
     doSomething($1) if $1; 
    } 
} 

क्या $some_value के आधार पर है, और आप कैसे रिक्त स्ट्रिंग और/या 0 से मेल खाने हैंडल करना चाहते हैं, तो आप या बिल्कुल $1 परीक्षण की आवश्यकता नहीं हो सकता है।

foreach (...) { 
    someFnc($1) if /.../; 
} 

लेकिन अगर आप अपनी शैली के साथ रहना चाहते हैं, तो एक विचार के रूप में इस जाँच: एक सूची

$_ = "this is the man that made the new year rumble"; 

$m = /(is)/ ? $1 : undef; 
$m = /(isnt)/ ? $1 : undef; 

print $m, "\n" if defined $m; 
+0

आप बिंदु खो रहे हैं। यह एक उदाहरण था (केवल आंशिक कोड)। सवाल बैकरेफर को रीसेट करने के बारे में है। – vol7ron

+3

@ vol7ron आप बिंदु खो रहे हैं। जब वे मान्य नहीं होते हैं तो वैश्विक चर के मानों को पढ़ना बंद करें। – hobbs

+0

@ हॉब्स: :) नहीं। आप सभी लोगों के बारे में पता होना चाहिए कि जब कोड अधिक जटिल हो जाता है तो आप इसे अधिक समझने योग्य बनाने के लिए अलग-अलग संरचना करते हैं। पूरे कारण से आप कभी-कभी 'अगर() {...}' बनाम 'करते हैं {...} अगर() ' – vol7ron

1

आप इसे इस तरह से करना shoud जैसा लगता है आप क्या चाहते हैं।

for ("match", "fail") { 
    my ($fake_1) = /(m.+)/; 
    doSomething($fake_1) if $fake_1; 
} 
+2

गंदे चीजें .. इसमें इस समस्या से निपटने के लिए और अधिक विचारशील तरीके हैं। –

+0

@mugenkenichi - मैं सहमत हूं, यह है, लेकिन यदि ओपी उस शैली को पसंद करता है, तो ... –

+1

'$ और' हर कीमत से बचा जाना चाहिए। आपके उदाहरण में '$ 1' का सटीक वही डेटा होगा और वैश्विक प्रदर्शन दंड से बचें। –

0

नियत कैप्चर के करीब व्यवहार करते हैं

1

मौजूदा, सहायक उत्तरों की मदद के लिए (और समझदार सिफारिश सामान्य रूप से एक बूलियन संदर्भ में एक मिलान आपरेशन के परिणाम का परीक्षण करने और कार्रवाई करने के केवल अगर परीक्षण के होते हुए भी सफल होता है करने के लिए):

अपने परिदृश्य के आधार पर आप समस्या को अलग-अलग संपर्क कर सकते हैं:

अस्वीकरण: मैं एक अनुभवी पर्ल प्रोग्रामर नहीं हूं; अगर इस दृष्टिकोण में समस्याएं हैं तो मुझे बताएं।

सभी regex से संबंधित विशेष चरों ($&, $1, ...) है कि ब्लॉक करने के लिए एक do { ... } ब्लॉक कार्यक्षेत्रों में मिलान आपरेशन संलग्न करें।

इस प्रकार, आप पहली जगह में सेट होने से इन विशेष चरों को रोकने के लिए एक do { ... } उपयोग कर सकते हैं (हालांकि ब्लॉक के बाहर पिछले एक regex आपरेशन से लोगों को प्रभाव में स्पष्ट रूप से रहेगा); उदाहरण के लिए:

$_="this is the man that made the new year rumble"; 

# Match in current scope; -> $&, $1, ... *are* set. 
/(is) /; 

# Match inside a `do` block; the *new* $&, $1, ... values 
# are set only *inside* the block; 
# `&& $1` passes out the block's version of `$1`. 
$do1 = do {/(made)/&& $1 }; 

print "\$1 == '$1'; \$do1 == '$do1'\n"; # -> $1 == 'is'; $do1 == 'made' 
  • इस दृष्टिकोण का लाभ यह है कि वर्तमान क्षेत्र के विशेष regex चर में से कोई भी सेट या बदल कर रहे हैं; इसके विपरीत स्वीकृत उत्तर, $&, और $' जैसे चर बदलता है।
  • नुकसान यह है कि आपको स्पष्ट रूप से ब्याज के चर को पारित करना होगा; आपको डिफ़ॉल्ट रूप से मिलान करने वाले ऑपरेशन का नतीजा मिलता है, और यदि आप केवल कैप्चर बफर की सामग्री में रूचि रखते हैं, तो यह पर्याप्त होगा।