Front page | perl.beginners |
Postings from April 2012
Re: Array of Hashes
Thread Previous
|
Thread Next
From:
Rob Dixon
Date:
April 12, 2012 07:10
Subject:
Re: Array of Hashes
Message ID:
4F86E22D.80902@gmx.com
On 12/04/2012 12:48, Paul.G wrote:
> Hi All
>
> New to this group, so hello to everybody.
>
> I am currently working on creating a Array of Hashes, note it is a
> work in progress. I appear to be getting some corruption when
> inputting data with the pvdisplay, I can't see why this is the case.
> I have put some print statements to see where I am going wrong and I
> suspect the logic of the script is incorrect. Below is the script:
>
>
> Scroll down further to see the output and hopefully it will make
> sense what I am asking.
>
> #!/usr/bin/perl
> use strict;
> use warnings;
>
> my @vggroup;
> my @PV;
> my $PV=0;
> my $Extents;
> my $AllocatedPE;
> my $rec = {};
> my $href;
> my $extent;
>
> open(CMD,"/usr/sbin/vgdisplay -v vg03|");
>
> while(<CMD>) {
> if (/PV Name/) {
> $PV = (split(/\s+/, $_))[3];
> push @PV, $PV;
> }
> }
>
> print "@PV \n";
>
> foreach $PV (@PV) {
> open(EXT,"/usr/sbin/pvdisplay $PV|");
> while(<EXT>) {<-- This is aware I appear to be going wrong, scroll down further.
> print $_;<---
> if (/Free PE/) {
> $AllocatedPE = (split(/\s+/,<EXT>))[2];
> $rec->{$PV} = $AllocatedPE;
> print "$PV ";
> print $rec->{$PV};
> print " \n";
> push @vggroup, $rec;
> }
> }
> }
> for $href (@vggroup) {
> print "{ ";
> for $extent ( keys %$href ) {
> print "$extent=$href->{$extent} ";
> }
> print "}\n";
>
> }
> close(EXT);
> close(CMD)
>
> Result:
> /dev/disk/disk46 /dev/disk/disk48 /dev/disk/disk47
> /dev/disk/disk46 159
> /dev/disk/disk48 159
> /dev/disk/disk47 0
> { /dev/disk/disk46=159 /dev/disk/disk48=159 /dev/disk/disk47=0 }
> { /dev/disk/disk46=159 /dev/disk/disk48=159 /dev/disk/disk47=0 }
> { /dev/disk/disk46=159 /dev/disk/disk48=159 /dev/disk/disk47=0 }
>
>
> /dev/disk/disk46 /dev/disk/disk48 /dev/disk/disk47
> --- Physical volumes ---
> PV Name /dev/disk/disk46
> VG Name /dev/vg03
> PV Status available
> Allocatable yes
> VGDA 2
> Cur LV 1
> PE Size (Mbytes) 64
> Total PE 159
> Free PE 0
> /dev/disk/disk46 159<-- The lines in bold are getting inserted, when reading with the pvdisplay. I should be seeing --> Allocated PE 0
> Stale PE 0 Why is this occurring?
> IO Timeout (Seconds) default
> Autoswitch On
> Proactive Polling On
>
> --- Physical volumes ---
> PV Name /dev/disk/disk48
> VG Name /dev/vg03
> PV Status available
> Allocatable yes
> VGDA 2
> Cur LV 1
> PE Size (Mbytes) 64
> Total PE 159
> Free PE 0
> /dev/disk/disk48 159
> Stale PE 0
> IO Timeout (Seconds) default
> Autoswitch On
> Proactive Polling On
>
> --- Physical volumes ---
> PV Name /dev/disk/disk47
> VG Name /dev/vg03
> PV Status available
> Allocatable yes
> VGDA 2
> Cur LV 0
> PE Size (Mbytes) 64
> Total PE 159
> Free PE 159
> /dev/disk/disk47 0
> Stale PE 0
> IO Timeout (Seconds) default
> Autoswitch On
> Proactive Polling On
Hi Paul and welcome to the list.
I can see a few things wrong with your code, but I have only a Windows
machine so cannot test any changes I am suggestion so please beware.
The reason you get the marked line in your output is because that is
what you have written. This loop
open(EXT,"/usr/sbin/pvdisplay $PV|");
while(<EXT>) {
print $_;
if (/Free PE/) {
$AllocatedPE = (split(/\s+/, <EXT>))[2];
$rec->{$PV} = $AllocatedPE;
print "$PV ";
print $rec->{$PV};
print " \n";
push @vggroup, $rec;
}
}
reads a line from the pvdisplay output and checks whether it contains
'Free PE'. If it does, this
$AllocatedPE = (split(/\s+/, <EXT>))[2];
reads another line (the 'Allocated PE' line), splits it on white space
and puts the third field - the extent - into $AllocatedPE. The code then
goes on to add a single hash element to $rec and then print the volume
name and extent.
The line read within the call to split is never displayed, and the loop
goes on to read and display the line after it in the while loop.
Another problem is that you are pushing the same hash reference $rec
onto @vggroup several times. There is no need for the array, as the hash
holds the information on all the volumes in the group on its own.
Other advice that may help is:
- Perl variables generally use lower-case letters and underscores, and
should be declared at the point of first use
- Lexical file handles should be used with the three-argument form of
open, and the status of /all/ opens should be checked before the file
handle is used
- By default the split operator splits $_ on whitespace, so split on its
own returns a list of separate non-whitespace fields found in $_. This
is usually what is wanted, as is the case here
- There may well be a module already written to do this. It is worh a
look at http://search.cpan.org unless your purpose is to learn the language
Below is a refactored version of your program taking these things into
account. As I explained I am unable to test it so I can only confirm
that it compiles.
HTH,
Rob
use strict;
use warnings;
open my $cmd, '-|', "/usr/sbin/vgdisplay -v vg03" or die $!;
my @pv;
while (<$cmd>) {
if (/PV Name/) {
my $pv = (split)[2];
push @pv, $pv;
}
}
print "@pv\n";
my $rec;
foreach my $pv (@pv) {
open my $ext, '-|', "/usr/sbin/pvdisplay $pv" or die $!;
while(<$ext>) {
print;
if (/Allocated PE/) {
my $allocated_pe = (split)[2];
$rec->{$pv} = $allocated_pe;
print "$pv => $allocated_pe\n";
}
}
}
use Data::Dumper;
print Dumper $rec;
Thread Previous
|
Thread Next