xingjin3131 has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks, Wondering whether you guys can give me some help on this. Say, I can get @allData in my program. The following is the content of @allData:
Test 1 of 1 bala bala bala. bala 138 end blah blah
I want to pick the header part from Test to 138 end. so I did like this:
@tmpHeader = grep /^Test\s+\d+\s+of\s+\d+$/../^\d+\s+end$/, @allData;
But somehow, when I tried to print @tmpHeader part, I got nothing. Can someone help me with this? Thanks a lot, Xing

Replies are listed 'Best First'.
Re: grep using regex
by ikegami (Patriarch) on Mar 01, 2009 at 21:12 UTC
    Works for me
    use strict; use warnings; my @allData = <DATA>; my @tmpHeader = grep /^Test\s+\d+\s+of\s+\d+$/../^\d+\s+end$/, @allDat +a; print @tmpHeader; __DATA__ Test 1 of 1 bala bala bala. bala 138 end blah blah
    Test 1 of 1 bala bala bala. bala 138 end

    Please pick more meaningful titles.

Re: grep using regex
by ysth (Canon) on Mar 02, 2009 at 00:07 UTC
    Because the .. flipflop operator remembers its state, you will run into problems if you use it in a loop like that and expect it to automatically reset each time you start the grep loop. That's only safe to do if you only ever run that grep once.
Re: grep using regex
by toolic (Bishop) on Mar 01, 2009 at 21:53 UTC
    If your actual data has any whitespace at the end (other than the newline), then that could explain why you are seeing no output. When I download your data, there is no extra whitespace, but perhaps it got cropped off when you posted it (or when I downloaded it). Perhaps try looking for extra whitespace using:
    @tmpHeader = grep /^Test\s+\d+\s+of\s+\d+\s*?$/../^\d+\s+end$/, @allDa +ta; ^^^^
Re: grep using regex (grepping with a regex)
by ww (Archbishop) on Mar 01, 2009 at 21:50 UTC

    Since you only sketch the actual output code, perhaps the problem is there?

    On the other hand, if your "print @tmpHeader" is your actual code, you might find

    for my $tmpHeader(@tmpHeader) { print '[' . $tmpHeader . '] '; }

    more readable, when you've solved the root issue.

    Update: "more readable" may be irrelevant; depends on the how -- precisely -- the data you show is formatted. ikegami's use of __DATA__ produces entirely readable output, but my initial instinct was to hardcode what you presented as:

    my @allData = ('Test 1 of 1', 'bala', 'bala', ...

    which produces the (desired) output as a single line without distinction among the elements.

    Obligatory suggestion: use strict; use warnings; may be helpful, especially if there's a slip betwixt cup and lip typo between your actual code and what you posted.

Re: grep using regex
by leslie (Pilgrim) on Mar 02, 2009 at 05:09 UTC
    Hi xing,

    Your code is working fine with this given input. But you need to use flip-flop operator very carefully.

    For example, if there is a file and we want to process only certain sections of it, then using the flip-flop operator the code can be written like:

    while () { if (/!! START !!/ .. /!! END !!/) { # process line } }

    Each time around the loop, the current line is checked by the flip-flop operator. If the line doesn't match /!! START !!/ then the operator returns false and the loop continues. When we reach the first line that matches /!! START !!/ then the flip-flop operator returns true and the code in the if block is executed. On subsequent iterations of the while loop, the flip-flop operator checks for matches again /!! END !!/, but it continues to return true until it finds a match. This means that all of the lines between the "!! START !!" and "!! END !!" markers are processed. When a line matches /!! END !!/ then the flip-flop operator returns false and starts checking against the first regex again.