Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Counting devices types, device sizes and number of devices.

by perl514 (Pilgrim)
on Jan 03, 2012 at 06:36 UTC ( #946006=perlquestion: print w/replies, xml ) Need Help??
perl514 has asked for the wisdom of the Perl Monks concerning the following question:

Venerated Monks,

I want to count the size and type of devices in my Storage Array. Here is how the output looks:

00C0 Not Visible ???:? 16D:D5 2-Way Mir N/Grp'd R +W 3 00C1 Not Visible ???:? 01A:D5 2-Way Mir N/Grp'd R +W 3 00C2 Not Visible ???:? 16B:D5 2-Way Mir N/Grp'd R +W 3 01D1 Not Visible ???:? 01D:D0 RAID-5 N/Grp'd R +W 8632 01D2 Not Visible ???:? 16D:D1 RAID-5 N/Grp'd R +W 8632 059B Not Visible ???:? 02D:D7 RAID-5 N/Grp'd (M) R +W 34526 0A77 Not Visible ???:? 02C:CB 2-Way Mir N/Grp'd (M) R +W 34526 0A7B Not Visible ???:? 02C:C9 2-Way Mir N/Grp'd (M) R +W 34526 0A7F Not Visible ???:? 02C:CD 2-Way Mir N/Grp'd (M) R +W 69052 0A83 Not Visible ???:? 02C:C5 RAID-5 N/Grp'd (M) R +W 34526 0A87 Not Visible ???:? 02C:C7 RAID-5 N/Grp'd (M) R +W 34526 0A8B Not Visible ???:? 01C:DB RAID-5 N/Grp'd (M) R +W 69052 0A8F Not Visible ???:? 01C:DD RAID-5 N/Grp'd (M) R +W 69052 0DB3 Not Visible ???:? 16D:C12 BCV+R5 N/Grp'd (M) R +W 34526 0DB7 Not Visible ???:? 16D:C16 BCV+R5 N/Grp'd (M) R +W 34526

I need the output so that it tells me something like:

Total Number of 2-Way Mir Devices of 3MB = 3 Total Number of 2-Way Mir Devices of 34GB = 3 Total Number of 2-Way Mir Devices of 69GB = 1 ============================================== Total Number of RAID-5 Devices of 34GB = 4 Total Number of RAID-5 Devices of 8.6GB = 2 Total Number of RAID-5 Devices of 69GB = 2 ============================================= Total Number of BCV+R5 Devices of 34 GB = 2



The output shown above is obtained by running command:

symdev -sid 1234 list -noport -noreserve|find /I "not visible"

So am trying to figure out how to pass the output of this command to a Filehandle so that I can try out stuff given in the node 504596. Is that a good way to go about it?


Now, thing is, in this output, there are 3 things that will vary.

1) The Type of RAID (2 Way Mir, or RAID5, Or BCV+R5, or something else).

2) The Size of Devices: This too will vary and could be different from the sizes given above.

3) the count of such type of devices.

I tried using split function, but I can get it to split on a line or a white space. Once I hold the split items in an array, I cant further split it, because the split function works in a scalar context.

Then I thought of using a hash, but from what I know, a hash can only have one value associated with a key. Is there a way to have multiple values associated with a hash key? I was planning to use 504596 as a reference to do it. Would that be the right way to go about this? Would redirecting the command output to a text file using a filehandle and then reading from it give me any advantages? I browsed through some articles, but nothing seems to make things clear for me.

I am not asking for a ready made code for this, as that will refute the very purpose of me trying to learn Perl. But I would kindly request me to guide to some pointers that will help me do it. Please help.

Perlpetually Indebted To PerlMonks

Replies are listed 'Best First'.
Re: Counting devices types, device sizes and number of devices.
by Sewi (Friar) on Jan 03, 2012 at 07:12 UTC

    Dear perl514,

    sounds like you got a good concept of solving your problem. Please add your sourcecode to the questions if possible for better help.

    I'd walk through the lines using while (<$fh>) and split each line at \t which returns an array of each line's information.

    Understanding might be easier if you print out the split result array using join or Data::Dumper until your script is working.

    If all you need is this output, you may use a trick to avoid using references (which isn't that easy for Perl beginners) by using a hash and the full text part ("Total Number of $split_result[4] Devices of $split_result[7]MB") as the key. The "++" operator easily adds one for each device found matching that key.

    The conversion of MB's to other units may be done using a if/elsif/else block or a CPAN module like Format::Human::Bytes.

      Hi Sewi,

      Thanks for the reply.

      I was planning to first use an array and then pass the elements of the array to a hash...Came out with very very basic stuff like this:

      #!/usr/bin/perl use warnings; use strict; my $command = `symdev -sid 1234 list -noport -noreserve|find /I "not v +isible"`; my @cmdline = split (/\n/, $command); my @chgcmdline = @cmdline[5,8]; print "@chgcmdline\n";

      But got stuck after this. Tried going through the node I have mentioned earlier and figuring out. The  symdev -sid 1234 list -noport -noreserve|find /I "not visible" is the command that gives the output mentioned in my post.

      BTW - I am using Strawberry Perl that came bundled with Padre IDE and I do sometimes use Padre. Awesome IDE. Mr. Gabor did a great thing by pre bundling a lot of modules. Neat stuff :)

      Perlpetually Indebted To PerlMonks

        The my $command = `symdev... doesn't do what you might think. It puts back one line of the symdev output in $command. If you split one line by \n, one item remains (the line without line ending), so your 5,8 are empty/undef because the array simply doesn't have that many items.

        Try this instead:

        open my $fh, '-|', 'symdev -sid 1234 list -noport -noreserve|find /I " +not visible"'; while (<$fh>) { chomp; my @line = split(/\t/); [...]

        The sample above runs the symdev (I'm a little bit unsure about the piping 3-argument-open, try out open my $fh, 'symdev -sid 1234 list -noport -noreserve|find /I "not visible" |'; (notice the final | after the command if it doesn't work) and offers it's output via filehandle $fh.

        The while loop reads the output line by line presenting every single line in the default variable $_ for one loop run.

        Read chomp's documentation to see what it does. split also uses the default variable if none specified and returns the columns of the line.

        I suggested a text hash key instead of the hash tree shown in another answer to your original post because you simple don't need the detailed data in your sample and keeping things simpler might be better for the moment.

        Another tip for you...With Perl, you can specify indicies from either side of an array or list. Some of your data lines have 8 some 9 things. So to get the 6th thing and the last thing, do it like this.. Main point is that by using negative index, you can get the last thing even if number of things varies. I think your actual data is tab separated? if so, then adjust accordingly.
        while (<DATA>) { my ($desc,$MB) = (split)[5,-1]; print "$desc $MB\n"; } =prints 2-Way 3 2-Way 3 2-Way 3 RAID-5 8632 RAID-5 8632 RAID-5 34526 2-Way 34526 2-Way 34526 2-Way 69052 RAID-5 34526 RAID-5 34526 RAID-5 69052 RAID-5 69052 BCV+R5 34526 BCV+R5 34526
        The index of -1 means "last item", -2 would mean next to last one, etc.

Re: Counting devices types, device sizes and number of devices.
by JavaFan (Canon) on Jan 03, 2012 at 07:23 UTC
    I'd use a hash, keyed on raid type and device size. You only need one value then: the count:

      Hi JavaFan,

      That's neat. Now I just need to figure out a way to get those values inside the hash.

      Perlpetually Indebted To PerlMonks

        use Data::Dumper; while (<DATA>) { chomp; @F = split /\t/; # <== place proper delimiter or regex $devices{$F[4]}{$F[-1]}++; } $Data::Dumper::Sortkeys = 1; print Dumper \%devices; # accessing for $type (sort keys %devices) { for $size (sort {$a <=> $b} keys %{$devices{$type}}) { print "$type $size $devices{$type}{$size} \n"; } }
        - J

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://946006]
Approved by Sewi
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (5)
As of 2018-06-25 05:11 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (126 votes). Check out past polls.