I'm probably being a little daft, but I'm sort of trying to get my head around the most elegant way to accomplish this, rather than one that 'just works'.
If I run a particular command I (long) list of entries, that look something like:
Symmetrix ID: Device Physical Name : \\.\PHYSICALDRIVE1 Device Symmetrix Name : 0062 (VCM) Device Serial ID : 6000062081 Symmetrix ID : 002020202220 Attached BCV Device : N/A Attached VDEV TGT Device : N/A Vendor ID : EMC Product ID : SYMMETRIX Product Revision : 5772 Device WWN : 222222222222222222 Device Emulation Type : FBA Device Defined Label Type: N/A Device Defined Label : N/A Device Sub System Id : 0x0001 Cache Partition Name : DEFAULT_PARTITION Device Block Size : 512 Device Capacity { Cylinders : 6 Tracks : 90 512-byte Blocks : 11520 MegaBytes : 6 KiloBytes : 5760 } Device Configuration : 2-Way Mir (Non-Exclusive Access) Device is WORM Enabled : No Device is WORM Protected : No SCSI-3 Persistent Reserve: Disabled Dynamic Spare Invoked : No Dynamic RDF Capability : None STAR Mode : No STAR Recovery Capability : None STAR Recovery State : NA Device Service State : Normal
This pattern is repeated a lot of times, once for each volume in my storage array.
What I'd really like to be able to do, is define a multi-line regexp, that matches 3 or 4 lines out of it (Device Symmetrix Name, Symmetrix ID, any one of the capacity entries, and the state of the SCSI-3 Persistent Reserve:) and then allows me to do some manner of 'foreach loop'.
So far, I've figured I can just do a line by line 'foreach', and set variables based on matching particular lines:
my $symm_id; foreach ( `symdev list -v` ) { if ( m/Symmetrix ID/ ) { $symm_id = ( m/Symmetrix ID\s+:\s+(\d+)/ ); } }
That sort of thing. But that seems ... well, just rather inelegant really, when I'm pretty sure I can do multi-line regexps. I just can't quite get my head around how to turn at multi-line RE into 'something useful' for a 'foreach' loop, with multiple values.
I've found the 'm' flag on the pattern match, and can knock together something that matches a single record.
my $text_to_parse = `symdev list -v`; my ( $dev, $sym, $config, $SCSI3 ) = ( $text_to_parse =~ m/Device Symmetrix Name\s+\:\s+([A-F0-9]+).*S +ymmetrix ID\s+\:\s+(\d+).*Device Capacity.*Cylinders\s+\:\s+(\d+).*SC +SI-3 Persistent Reserve\s+\:\s+(\w+)/m ); print "$dev, $sym, $config, $SCSI3\n";
Well, approximately - that's not quite what I want to do, as the greedy matches will eat the intervening chunks of the command output. But essentially, I want to do that 'per record'. Given the output of this particular command generates around 400Mb, I may end up dumping it to a file first.

In reply to Multiple line records from a command string by Preceptor

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.