2010-12-15 13 views
13

मैं पर्ल में ब्रैकेट आदि में संलग्न पाठ से मेल खाना चाहता हूं। मैं उसे कैसे कर सकता हूँ?क्या मैं संतुलित पाठ से मिलान करने के लिए पर्ल नियमित अभिव्यक्तियों का उपयोग कर सकता हूं?


यह official perlfaq से एक प्रश्न है। हम importing the perlfaq to Stack Overflow हैं।

उत्तर

22

यह official FAQ answer किसी भी बाद के संपादन से कम है।

आपकी पहली कोशिश शायद Text::Balanced मॉड्यूल होनी चाहिए, जो पर्ल 5.8 के बाद पर्ल मानक लाइब्रेरी में है। मुश्किल पाठ से निपटने के लिए इसमें कई प्रकार के कार्य हैं। Regexp::Common मॉड्यूल आपके द्वारा उपयोग किए जा सकने वाले डिब्बाबंद पैटर्न प्रदान करके भी मदद कर सकता है।

पर्ल 5.10 के रूप में, आप पुनरावर्ती पैटर्न का उपयोग करके नियमित अभिव्यक्तियों के साथ संतुलित पाठ से मिलान कर सकते हैं। पर्ल 5.10 से पहले, आपको (??{}) अनुक्रमों में पर्ल कोड का उपयोग करने जैसी विभिन्न चालों का सहारा लेना पड़ा।

यहां एक पुनरावर्ती नियमित अभिव्यक्ति का उपयोग करके एक उदाहरण दिया गया है। लक्ष्य कोण के ब्रैकेट के भीतर सभी टेक्स्ट को कैप्चर करना है, जिसमें नेस्टेड कोण ब्रैकेट में टेक्स्ट भी शामिल है। इस नमूना पाठ में दो "प्रमुख" समूह हैं: घोंसले के एक स्तर वाले समूह और घोंसले के दो स्तर वाले समूह।

I have some <brackets in <nested brackets> > and 
<another group <nested once <nested twice> > > 
and that's it. 

नियमित अभिव्यक्ति संतुलित पाठ मैच के लिए दो नए (पर्ल 5.10 तक) नियमित अभिव्यक्ति सुविधाओं का उपयोग करता: कोण कोष्ठक में पांच की कुल समूह हैं। ये perlre में शामिल हैं और यह उदाहरण उस दस्तावेज़ में एक का एक संशोधित संस्करण है।

सबसे पहले, किसी भी मात्रात्मक को नया स्वामित्व + जोड़ना सबसे लंबा मैच पाता है और बैकट्रैक नहीं करता है। यह महत्वपूर्ण है क्योंकि आप रिकर्सन के माध्यम से किसी भी कोण ब्रैकेट को संभालना चाहते हैं, बैकट्रैकिंग नहीं। समूह [^<>]++ बैकट्रैकिंग के बिना एक या अधिक गैर-कोण ब्रैकेट पाता है।

दूसरा, नया (?PARNO)PARNO द्वारा दिए गए विशेष कैप्चर समूह में उप-पैटर्न को संदर्भित करता है। निम्नलिखित रेगेक्स में, पहला कैप्चर समूह संतुलित टेक्स्ट पाता है (और याद करता है), और आपको नेस्टेड टेक्स्ट को पाने के लिए पहले बफर के भीतर उसी पैटर्न की आवश्यकता होती है। यह रिकर्सिव हिस्सा है। (?1) बाहरी कैप्चर समूह में पैटर्न को रेगेक्स के एक स्वतंत्र भाग के रूप में उपयोग करता है।

यह सब एक साथ रखें, आपके पास:

#!/usr/local/bin/perl5.10.0 

my $string =<<"HERE"; 
I have some <brackets in <nested brackets> > and 
<another group <nested once <nested twice> > > 
and that's it. 
HERE 

my @groups = $string =~ m/ 
     (     # start of capture group 1 
     <     # match an opening angle bracket 
      (?: 
       [^<>]++  # one or more non angle brackets, non backtracking 
        | 
       (?1)  # found <or>, so recurse to capture group 1 
      )* 
     >     # match a closing angle bracket 
     )     # end of capture group 1 
     /xg; 

$" = "\n\t"; 
print "Found:\n\[email protected]\n"; 

उत्पादन पता चलता है कि पर्ल दो प्रमुख समूहों पाया:

Found: 
    <brackets in <nested brackets> > 
    <another group <nested once <nested twice> > > 

कुछ अतिरिक्त कार्यों के साथ, आप के सभी प्राप्त कर सकते हैं कोण ब्रैकेट में समूह भी भले ही वे अन्य कोण ब्रैकेट में हों। प्रत्येक बार जब आप संतुलित मिलान प्राप्त करते हैं, तो अपने बाहरी डिलीमीटर को हटा दें (यही वह है जिसे आपने अभी मिलान किया है, इसलिए इसे दोबारा मेल न करें) और प्रक्रिया के लिए तारों की कतार में जोड़ें। ऐसा तब तक करें जब तक आपको कोई मिलान न मिले:

#!/usr/local/bin/perl5.10.0 

my @queue =<<"HERE"; 
I have some <brackets in <nested brackets> > and 
<another group <nested once <nested twice> > > 
and that's it. 
HERE 

my $regex = qr/ 
     (     # start of bracket 1 
     <     # match an opening angle bracket 
      (?: 
       [^<>]++  # one or more non angle brackets, non backtracking 
        | 
       (?1)  # recurse to bracket 1 
      )* 
     >     # match a closing angle bracket 
     )     # end of bracket 1 
     /x; 

$" = "\n\t"; 

while(@queue) 
    { 
    my $string = shift @queue; 

    my @groups = $string =~ m/$regex/g; 
    print "Found:\n\[email protected]\n\n" if @groups; 

    unshift @queue, map { s/^<//; s/>$//; $_ } @groups; 
    } 

आउटपुट सभी समूहों को दिखाता है। बाहरीतम मैच पहले और घोंसले वाले मैचों को बाद में दिखाते हैं:

Found: 
    <brackets in <nested brackets> > 
    <another group <nested once <nested twice> > > 

Found: 
    <nested brackets> 

Found: 
    <nested once <nested twice> > 

Found: 
    <nested twice> 
संबंधित मुद्दे

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