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

Sorry If I have bothered you with RegEx posts, But it seems I have a mental block for them at the moment!

I have this data
version 2.0(3) vsan database vsan 1000 name "SANMGMT_Green" vsan 1010 name "IMIS_Green" vsan 1030 name "TEMS_Green" vsan 1050 name "IPBilling_Green" vsan 1060 name "Greek_Green" vsan 1900 name "SRDF_Green" vsan 3120 name "TAPEA_GREEN" power redundancy-mode combined force logging server 10.33.34.235 6 fcdomain domain 20 static vsan 1 fcdomain fcid persistent vsan 1 fcdomain domain 20 static vsan 1000 fcdomain fcid persistent vsan 1000 fcdomain domain 20 static vsan 1010 fcdomain fcid persistent vsan 1010 fcdomain domain 20 static vsan 1030 fcdomain fcid persistent vsan 1030 fcdomain domain 20 static vsan 1050 fcdomain fcid persistent vsan 1050 fcdomain domain 20 static vsan 1060 fcdomain fcid persistent vsan 1060 fcdomain domain 20 static vsan 1900 fcdomain fcid persistent vsan 1900 fcdomain fcid persistent vsan 3120 fcdomain fcid database vsan 1060 wwn 50:06:04:84:4a:36:f4:d8 fcid 0x6d0000 dynamic vsan 1060 wwn 50:06:04:84:4a:36:f4:d6 fcid 0x6d0001 dynamic vsan 1050 wwn 50:06:04:84:4a:36:f4:d7 fcid 0x140001 dynamic vsan 1060 wwn 50:06:04:8c:4a:36:f4:c2 fcid 0x6d0002 dynamic
and I want to grab the following data from the above
vsan 1000 = "SANMGMT_Green" vsan 1010 = "IMIS_Green" vsan 1030 = "TEMS_Green" vsan 1050 = "IPBilling_Green" vsan 1060 = "Greek_Green" vsan 1900 = "SRDF_Green" vsan 3120 = "TAPEA_GREEN"
So I put together this bit of code
local $/ = ""; while ( my $record = <DATA> ) { my ($vsan) = $record =~ /^\s+vsan\s(\d+)/; my ($vname) = $record =~ /^\s+vsan\s\d+name\s(.+)$/; print "$vsan, $vname\n"; }
What I mean here is;
with $vsan : from the beginning, there is at least one white space, followed by the word vsan, then another space, then few digits which I want Perl to grab.

with $vname : from the beginning, there is at least one white space, followed by the word vsan, then another space, then few digits, followed by the word ‘name’, then another white space, then grab everything till the end of that line

Well this makes perfect sence to me however I do not get any output!

Can I ask if someone can show how is this done?

Thanks

################### UPDATE ######################

I'll prove myself wrong

got rid of local $/

And used this code
next unless ($record =~ /^\s+vsan\s(\d+)\sname\s(.+)$/); print $record;
Blackadder

Replies are listed 'Best First'.
Re: Prove me wrong,...please (yet more regex blues).
by graff (Chancellor) on Sep 23, 2005 at 13:08 UTC
    I think you want something like this:
    my ( $vsan, $vname ) = ( $record =~ /^\s+vsan\s+(\d+)\s+name\s+(.+)/ ) +;
    (the parens around the rhs are probably optional, but I like having them there; the ones around the lhs are mandatory, of course)

    updated to include the literal string "name" in the regex match.

      This might work:
      while (<DATA>) { s/name/=/; print "$_" if /^\s+/ && /=/; }
        While that kind of code is clever and fits a single case, it doesn't really explain what it's doing, and modifies the original data.

        Your choices of landmarks to match seem unlikely as the key determiners for the desired information. What if other lines are included (now or in the future) with similar formats that have leading spaces or equal signs? I would more likely guess that the keywords and string-delimited labels are the important parts to watch.

        Literate code helps the maintenance programmer (or yourself) figure out how it works later.

        while (<DATA>) { next if not /^ \s* vsan \s+ (\d+) \s+ # $1 name \s+ ( \" .*? \" ) # $2 $ /x; print "vsan $1 = $2\n"; }
        As you and your team of maintainers get more familiar with regular expressions, you may tighten that up with less spacing and less commentary, but the pattern is specific and includes the obvious visual landmarks which are important for the programmer to understand.

        --
        [ e d @ h a l l e y . c c ]