Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Help with Multiple line RegEx

by blackadder (Hermit)
on Oct 10, 2005 at 10:11 UTC ( [id://498761]=perlquestion: print w/replies, xml ) Need Help??

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

Dear All, Need your divine help once again!

I have the following data and script
#! c:/perl/bin/perl.exe # # $|++; AUTOLOAD; use strict; use warnings 'all'; my $Rec; while (<DATA>) { chomp; next if ($_ eq ""); $Rec->{$1} = $2 if ($_=~ /^-+\s+show (switchname)\s+-+\n(\w+)\*+/mg +); print "$Rec->{$1} = $2\n"; } close DATA; __DATA__ show tech-support details -------------------- show switchname ------------------ CCC217_ANG_GREEN ****************************************************************** show tech-support details -------------------- show switchname ------------------ CCC218_ANG_GREEN ****************************************************************** show tech-support details -------------------- show switchname ------------------ CCC219_ANG_GREEN ****************************************************************** show tech-support details -------------------- show switchname ------------------ CCC220_ANG_GREEN ******************************************************************
What I want to capture is the data after the string 'show switchname ------------------' and before the line "****************************************************************** "

so According to my RegEx then; from the start, any multiple -+,at least one space, followed by show, capture (switchname), followed by another at least one space, multiple -+ and \n, then capture any word+ before multiple *.

Although it makes sence to me but I dont get any output!

Can a holy monk enlighten me please on where and why RegEx is not working!!

Blackadder

Replies are listed 'Best First'.
Re: Help with Multiple line RegEx
by GrandFather (Saint) on Oct 10, 2005 at 10:45 UTC

    You may find this helpfull if your real data is of modest size:

    use strict; use warnings 'all'; my $str = do {local $/ = undef; <DATA>}; my @Rec = $str =~ /-+\s+show switchname\s+-+[^\w]+(\w+)/ig; print "$_\n" for @Rec;

    Prints:

    CCC217_ANG_GREEN CCC218_ANG_GREEN CCC219_ANG_GREEN CCC220_ANG_GREEN

    Update: Silly programmer mixed input and output seperators :(


    Perl is Huffman encoded by design.
Re: Help with Multiple line RegEx
by wfsp (Abbot) on Oct 10, 2005 at 10:32 UTC
    Your while loop is reading one line at a time. So perhaps something like this might help?

    while (<DATA>) { chomp; next if /^$/; next if /^[* -]/; print "$_\n"; }

    update:
    Corrected regex

      Thanks for this

      But I want to make sure that I grab the data immidiatly follows the string "-+ show switchname -+".This is in case if there is another pattern similer to your suggestion.
      Blackadder
Re: Help with Multiple line RegEx
by reasonablekeith (Deacon) on Oct 10, 2005 at 10:47 UTC
    or, if you can slurp the whole file, just use a single regex...
    my $data = join("\n", <DATA>); while ($data =~ /-+ show (\S+) -+\s(.*?)\s\*{40}/sg) { print "switchname $1\n"; print "data $2\n"; }
    ---
    my name's not Keith, and I'm not reasonable.
      this is kool too. But I thought the \* is {66}! Anyway,...Thanks alot
      Blackadder
Re: Help with Multiple line RegEx
by gargle (Chaplain) on Oct 10, 2005 at 10:57 UTC

    Hi,

    What about the following:

    #!/usr/bin/perl use strict; use warnings; while (<DATA>) { # only check between --- show switchname --- and ***** if ( /^-+ show switchname -+/ .. /^\*+/ ) { # only pick up the word between these two lines print "$1\n" if /(^\w+)/; } } __DATA__ show tech-support details -------------------- show switchname ------------------ CCC217_ANG_GREEN ****************************************************************** show tech-support details -------------------- show switchname ------------------ CCC218_ANG_GREEN ****************************************************************** show tech-support details -------------------- show switchname ------------------ CCC219_ANG_GREEN ****************************************************************** show tech-support details -------------------- show switchname ------------------ CCC220_ANG_GREEN ******************************************************************

    The code indicates clearly what it's about. We use .. to only look at 'blocks' in the file and then process the block lines with a regexp looking up a single word (the first word on the line actually).

    ---- show ---- doesn't begin with a word, and,

    ************** isn't a word either.

    Using .. makes updating the code later on very easy. (Imagine that there are 2 lines between ---- and ****

    --
    if ( 1 ) { $postman->ring() for (1..2); }
      That's it almost. The OP wanted to catch the data between those lines. So, modifying your code, something like this should work:
      if ( my $hit= /^-+ show switchname -+/ .. /^\*+/ ) { next if $hit==1 or $hit =~ /e0$/i; # When we're here, it's one of those lines in between # Now do whatever you want with the data.... } <!-- Node text goes above. Div tags should contain sig only --> <div class="pmsig"><div class="pmsig-253915"> <hr><code>$\=~s;s*.*;q^|D9JYJ^^qq^\//\\\///^;ex;print
      Yes, This is good

      But I think it can all be done in one liner!

      Like Browser_UK suggestion.
      $Rec->{$1} = $2 if ($_=~ /-+\s+show (switchname)\s+-+\n(\w+)\n\*+/mg);
      Blackadder

        TIMTOWTDI

        It's easy to write code that a computer can read, it's not so easy to write code that a human can understand.

        It's a choice. The 'select' can easily be written as a single regexp. But think about later? What's easier to adapt? The single statement or the multiple statement?

        I, for one, like code that shows its intend, even when coding in perl ;)

        --
        if ( 1 ) { $postman->ring() for (1..2); }
Re: Help with Multiple line RegEx
by BrowserUk (Patriarch) on Oct 10, 2005 at 11:05 UTC

    If your file is too big for slurping, you can set $/="*\n", so that you read mutiple lines each time.

    #! c:/perl/bin/perl.exe # # $|++; AUTOLOAD; use strict; use warnings 'all'; my $Rec; $/ = "*\n"; ## Define the record separator to the end of the multiple +line record while (<DATA>) { chomp; next if ($_ eq ""); $Rec->{$1} = $2 if ($_=~ /-+\s+show (switchname)\s+-+\n(\w+)\n\*+/m +g); print "$1 $2\n"; } close DATA;

    Note. You were missing an \n between (w+) and \*+. and as coded, $1 will always be 'switchname' and so the values will always overlay each other. I'm not sure what you were looking to do here?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
      Now what can I say?...Thanks indeed Buddy

      I have been humbled - yet again - by your vast knowledge Mr. Browser_UK.

      Thanks to all, I have learnt one or two things about RegEx.

      VIVA PERLMONKS
      Blackadder
Re: Help with Multiple line RegEx
by Perl Mouse (Chaplain) on Oct 10, 2005 at 10:37 UTC
    Considering that you read in the lines one by one, you'll never match a pattern spanning more than one line. If the file is short, read in the entire line. If not, use a two-line buffer, applying the regex on the concatenation of the buffer. Alternatively, split the regex in two. Match the first part - if there's a match, read in the next line and match the second part. If the second part matches, record it. If the second part doesn't match, redo the current iteration.
    Perl --((8:>*

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://498761]
Approved by wfsp
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (2)
As of 2024-04-17 02:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found