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

Input: system command

Output: HoH

Problem: system command with lots of garbage output.

Goal: To create a HoH with SAN_VC0_## as the key and the hdisk string plus its serial as the values.

All I need is a single hdisk# string from the below system command output. Thank you! Here is what I have tried:

use strict; for my $lun ( ('SAN_VC0_42','SAN_VC0_43') ) { $luns_to_hdisk {$lun} = { grep /hdisk\d+/, qx(vxdisk list $lun) } ; } print Dumper(\%luns_to_hdisk); $VAR1 = { 'SAN_VC0_43' => { 'hdisk855 state=enabled ' => 'hdisk920 state=enabled ', 'hdisk587 state=enabled ' => 'hdisk652 state=enabled ', 'hdisk51 state=enabled ' => 'hdisk116 state=enabled ', 'hdisk319 state=enabled ' => 'hdisk384 state=enabled ' }, 'SAN_VC0_42' => { 'hdisk571 state=enabled ' => 'hdisk636 state=enabled ', 'hdisk35 state=enabled ' => 'hdisk100 state=enabled ', 'hdisk303 state=enabled ' => 'hdisk368 state=enabled ', 'hdisk839 state=enabled ' => 'hdisk904 state=enabled ' } };
Output of system command:
$ vxdisk list SAN_VC0_42 Device: SAN_VC0_42 devicetag: SAN_VC0_42 type: auto info: format=none flags: online ready private autoconfig invalid pubpaths: block=/dev/vx/dmp/SAN_VC0_42 char=/dev/vx/rdmp/SAN_VC0_42 Multipathing information: numpaths: 8 hdisk35 state=enabled hdisk100 state=enabled hdisk303 state=enabled hdisk368 state=enabled hdisk571 state=enabled hdisk636 state=enabled hdisk839 state=enabled hdisk904 state=enabled

Replies are listed 'Best First'.
Re: trying HoH
by gone2015 (Deacon) on Nov 11, 2008 at 01:47 UTC

    OK, so let's unpack what you did:

    for my $lun ( ('SAN_VC0_42','SAN_VC0_43') ) { $luns_to_hdisk {$lun} = { grep /hdisk\d+/, qx(vxdisk list $lun) } +; } ;
    • the qx(vxdisk list $lun) is invoked in List Context, so will return a list, each entry of which is one line as returned by the vxdisk command -- complete with line-ending.

    • the grep returns a list which is a subset of the list returned by qx, selecting the entries which match /hdisk\d+/

    • that is enclosed by {}, which in this case comprise an anonymous hash constructor -- constructing a hash with the even numbered entries that matched /hdisk\d+/ as keys, and the odd numbered entries as values.

    • a reference to that anonymous hash is assigned to $luns_to_hdisk{$lun}

    • that is done for $lun set to 'SAN_VC0_42' and then 'SAN_VC0_43'

    so much, so straightforward.

    I guess that's not what you intended ?

    What did you have in mind ?

    If you want $luns_to_hdisk{$lun} to be a list of the /hdisk\d+/ lines, you are very nearly there... you just need the anonymous list constructor [], not the anonymous hash constructor {}. That would be an HoL, though -- which is not what you were apparently wanting ?

    You may want to consider a chomp somewhere or other to remove the line-endings from the selected lines. It's not clear whether you want the 'state=enabled' part, and if not you need a little extra code there.

Re: trying HoH
by toolic (Bishop) on Nov 11, 2008 at 02:06 UTC
    You did not show us what you want the contents of your HoH to be. Is is something like this?
    $VAR1 = { 'SAN_VC0_42' => { 'hdisk368' => 'state=enabled', 'hdisk303' => 'state=enabled', 'hdisk636' => 'state=enabled', 'hdisk35' => 'state=enabled', 'hdisk904' => 'state=enabled', 'hdisk571' => 'state=enabled', 'hdisk100' => 'state=enabled', 'hdisk839' => 'state=enabled' } };

    If so, then this more verbose code will accomplish that:

    my @vxdisk_lines = qx(vxdisk list $lun); chomp @vxdisk_lines; my @hdisks = grep {/hdisk\d+/} @vxdisk_lines; my %h; for (@hdisks) { my ($k, $v) = split; $h{$k} = $v; } $luns_to_hdisk{$lun} = \%h;
      You all definitely helped! Thx agn. I want my end result to look like b/c all I need is one hdisk string b/c they are all different logical paths to the same LUN. I don't need the 'state=enabled' part and tried using (split)[0] but failed. Once I have this I will then integrate another system command (or a 2nd hash value) on the value hdisk368 for example to get its serial number.
      END_RESULT $VAR1 = { 'SAN_VC0_42' => { 'hdisk368' => 'state=enabled', } };
      I was playing with, but was side-tracked.
      print ((<DATA>)[-1]); __DATA__ Device: SAN_VC0_42 devicetag: SAN_VC0_42 type: auto info: format=none flags: online ready private autoconfig invalid pubpaths: block=/dev/vx/dmp/SAN_VC0_42 char=/dev/vx/rdmp/SAN_VC0_42 Multipathing information: numpaths: 8 hdisk35 state=enabled hdisk100 state=enabled hdisk303 state=enabled hdisk368 state=enabled hdisk571 state=enabled hdisk636 state=enabled hdisk839 state=enabled hdisk904 state=enabled
Re: trying HoH
by kyle (Abbot) on Nov 11, 2008 at 01:53 UTC

    I can't tell what you want the end structure to look like. My guess is that this is what you want:

    $luns_to_hdisk {$lun} = { map { chomp; split } grep { /hdisk\d+/ } qx(vxdisk list $lun) }