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

निम्नलिखित regex हालांकि काम नहीं कर रहा है। स्क्रिप्ट अपेक्षित आउटपुट के बजाय { def \} प्रिंट करती है: { def \} hij \\\} klm }। मैं क्या गलत कर रहा हूं? मैं इसे कैसे सुधार सकता हूँ?

my $str = 'abc { def \} hij \\\} klm } nop';

if ( $str =~ m/
              (
                \{
                  (?: \\\\
                  |   \\[\{\}]
                  |   [^\{\}]+
                  |   (?-1)
                  )*
                \}
              )
              /x
) { print $1, "\n" }
2
n.r. 4 पद 2015, 19:41

2 जवाब

सबसे बढ़िया उत्तर

आप निम्नलिखित रेगेक्स का उपयोग कर सकते हैं जो किसी भी बच गए प्रतीकों का समर्थन करेंगे:

(?<=^|\\.|[^\\])({(?>\\.|[^{}]|(?1))*})

टिप्पणियों के साथ VERBOSE संस्करण:

(?<=^|\\.|[^\\]) # Before `{` there is either start of string, escaped entity or not a \
(
   {            # Opening {
     (?>        # Start of atomic group
          \\.   # Any escaped symbol 
         |      
          [^{}] # any symbol but `{` and `}`
         | 
          (?1)  # Recurse the first subpattern
     )*         # repeat the atomic group 0 or more times
   }            # closing brace
)

regex डेमो देखें

अद्यतन

चूंकि उपरोक्त रेगेक्स पहले चरित्र के रूप में एक बची हुई उद्घाटन ब्रेस से मेल खा सकता है, इसलिए आप उपयोग कर सकते हैं

[^\\{}]*(?:\\.[\\{}]*)*(?<!\\)({(?>\\.|[^{}]|(?1))*})

regex डेमो देखें

यह सभी बच गए और अनावश्यक सबस्ट्रिंग से मेल खाएगा और समूह 1 में केवल वैध सब्सट्रेट पर कब्जा कर लेगा।

2
Wiktor Stribiżew 4 पद 2015, 17:48

यहाँ दो समस्याएं हैं - $str में स्ट्रिंग का मान और रेगेक्स पैटर्न

यहां तक कि एक एकल-उद्धृत स्ट्रिंग के भीतर, बैकस्लैश को बच जाना चाहिए जब दो एक साथ दिखाई देते हैं या जब वे स्ट्रिंग में अंतिम चरित्र के रूप में दिखाई देते हैं। बैकस्लैश की एक जोड़ी एक तक कम हो जाती है, इसलिए अंतिम स्ट्रिंग में \\\} सबस्ट्रिंग \\} उत्पन्न करेगा। एक समापन ब्रेस द्वारा पीछा किए जाने वाले तीन बैकस्लैश का उत्पादन करने के लिए, आपको कोड में छह बैकस्लैश चाहिए - \\\\\\} (हालांकि पांच करेंगे)

आपका रेगेक्स पैटर्न गलत है क्योंकि चरित्र वर्ग [^{}] भी एक एकल बैकस्लैश से मेल खाएगा, जो इसे एक बचा हुआ ब्रेस अनुक्रम के भाग के रूप में पहचाना जाने से रोकेगा। तो वैकल्पिक [^{}\\]+ स्ट्रिंग से def \ मेल कर रहा है, जिससे } पीछे हट रहा है

यह प्रोग्राम वही करता है जो आपको चाहिए

use strict;
use warnings 'all';

my $str = 'abc { def \} hij \\\\\\} klm } nop';

print $str, "\n";

if ( $str =~ m/
              (
                \{
                  (?:
                  [^{}\\]+  |
                  \\.       |
                  (?-1)
                  )*
                \}
              )
              /xs ) {

    print $1, "\n";
}

उत्पादन

abc { def \} hij \\\} klm } nop
{ def \} hij \\\} klm }
3
Borodin 4 पद 2015, 17:19