2012-05-14 6 views
8

मैं इस तरह पाठ है:पर्ल regex

00:00 stuff 
00:01 more stuff 
multi line 
    and going 
00:02 still 
    have 

तो, मैं एक ब्लॉक अंत, बस एक नए ब्लॉक शुरुआत नहीं है।

मैं रिकर्सिवली सभी ब्लॉक प्राप्त करना चाहते हैं:

1 = 00:00 stuff 
2 = 00:01 more stuff 
multi line 
    and going 

आदि

bellow कोड केवल मुझे इस देता है: गलत

$VAR1 = '00:00'; 
$VAR2 = ''; 
$VAR3 = '00:01'; 
$VAR4 = ''; 
$VAR5 = '00:02'; 
$VAR6 = ''; 

मैं क्या कर रहा हूँ?

my $text = '00:00 stuff 
00:01 more stuff 
multi line 
and going 
00:02 still 
have 
    '; 
my @array = $text =~ m/^([0-9]{2}:[0-9]{2})(.*?)/gms; 
print Dumper(@array); 

उत्तर

2

इस चाल करना चाहिए:

आप भी इस समाधान पर विचार हो सकता है। अगले \ d \ d: \ d \ d की शुरुआत ब्लॉक अंत के रूप में की जाती है।

$Str = '00:00 stuff 
00:01 more stuff 
multi line 
    and going 
00:02 still 
    have 
00:03 still 
    have' ; 

@Blocks = ($Str =~ m#(\d\d:\d\d.+?(?:(?=\d\d:\d\d)|$))#gs); 

print join "--\n", @Blocks; 
+1

आपका गैर पर कब्जा करने कोष्ठक '(? ...)' यहां बेमानी हैं, (के रूप में '=?। ..) 'विकल्प का भी उपयोग कर सकते हैं। साथ ही, मुझे लगता है कि आप अभी भी 'सख्त' अनुपालन कोड नहीं लिख रहे हैं, जो मेरी पुस्तक में खराब है, क्योंकि यह बुरी आदत को प्रोत्साहित करता है। – TLP

+1

मैंने दूसरे धागे में ** उपयोग (आईएनजी) सख्त ** के बारे में पर्याप्त स्पष्टीकरण दिया है। क्या आप इसे करने से रोकते हैं? – tuxuday

+1

हाँ, मुझे बुरा लगता है। क्या आप गैर-सख्त कोड पोस्ट करना बंद कर देंगे? यह एक सीखने का माहौल है, यह आपको उस कोड को पोस्ट करने के लिए * कुछ भी नहीं लेता है जो अच्छे अभ्यास को प्रोत्साहित करता है, अब यह करता है? – TLP

0

आपका समस्या यह है कि .*? उसी तरह है कि .* लालची है में गैर लालची है। जब इसे मजबूर नहीं किया जाता है, तो यह जितना संभव हो उतना छोटा होता है, जो इस मामले में खाली स्ट्रिंग है।

तो, आपको अपने कब्जे को लंगरने के लिए गैर-लालची मैच के बाद कुछ चाहिए। मैं इस regex के साथ आया था:

my @array = $text =~ m/\n?([0-9]{2}:[0-9]{2}.*?)(?=\n[0-9]{2}:|$)/gs; 

जैसा कि आप देख, मैं हटा दिया /m विकल्प सही ढंग से देखो आगे दावे में स्ट्रिंग के अंत से मेल करने में सक्षम हो।

my @array = split /(?=[0-9]{2}:[0-9]{2})/, $text; 
4

संस्करण 5.10.0 named capture groups कि nontrivial पैटर्न मिलान के लिए उपयोगी होते हैं की शुरुआत की।

(?'NAME'pattern)
(?<NAME>pattern)

एक नामित कब्जा समूह। सामान्य कैप्चरिंग कोष्ठक के हर मामले में समान () लेकिन अतिरिक्त तथ्य के लिए कि समूह को विभिन्न नियमित अभिव्यक्ति संरचनाओं (जैसे \g{NAME}) में नाम से संदर्भित किया जा सकता है और %+ या %- के माध्यम से सफल मिलान के बाद नाम से पहुंचा जा सकता है। %+ और %- हैश पर अधिक जानकारी के लिए perlvar देखें।

यदि एकाधिक विशिष्ट कैप्चर समूहों का एक ही नाम है तो $+{NAME} मिलान में बाएंतम परिभाषित समूह को संदर्भित करेगा।

फॉर्म (?'NAME'pattern) और (?<NAME>pattern) समकक्ष हैं।

नामित कैप्चर समूह हमें निम्नलिखित में रेगेक्स के भीतर उप-पैटर्न का नाम देने की अनुमति देते हैं।

use 5.10.0; # named capture buffers 

my $block_pattern = qr/ 
    (?<time>(?&_time)) (?&_sp) (?<desc>(?&_desc)) 

    (?(DEFINE) 
    # timestamp at logical beginning-of-line 
    (?<_time> (?m:^) [0-9][0-9]:[0-9][0-9]) 

    # runs of spaces or tabs 
    (?<_sp> [ \t]+) 

    # description is everything through the end of the record 
    (?<_desc> 
     # s switch makes . match newline too 
     (?s: .+?) 

     # terminate before optional whitespace (which we remove) followed 
     # by either end-of-string or the start of another block 
     (?= (?&_sp)? (?: $ | (?&_time))) 
    ) 
) 
/x; 

में

my $text = '00:00 stuff 
00:01 more stuff 
multi line 
and going 
00:02 still 
have 
    '; 

while ($text =~ /$block_pattern/g) { 
    print "time=[$+{time}]\n", 
     "desc=[[[\n", 
     $+{desc}, 
     "]]]\n\n"; 
} 

आउटपुट के रूप में यह प्रयोग करें:

$ ./blocks-demo 
time=[00:00] 
desc=[[[ 
stuff 
]]] 

time=[00:01] 
desc=[[[ 
more stuff 
multi line 
and going 
]]] 

time=[00:02] 
desc=[[[ 
still 
have 
]]]
+1

आधुनिक Perl5 फिर से वास्तव में महान उदाहरण :) – XoR