Operating System - HP-UX
1827286 Members
2620 Online
109717 Solutions
New Discussion

Re: Perl script help required

 
SOLVED
Go to solution
Akram Shaik
Frequent Advisor

Perl script help required

Hi all ,

I am reading some contents from a file

File contains the following data
lvdata 20000 /ora/data
lvappl 2048 /ora/appl
lvcs 1024 /ora/scs
lvora 2048 /ora

I want to store the lvinfo in an array variable,
the LV size in another array variable and the FS in another array variable.


I am not able to do that using perl. I am beginner in perl . Kindly let me know if this is possible and how .

Thanks for all .

Regards,
Akram
when everyting is coming your way then you are in the wrong lane
13 REPLIES 13
David Bellamy
Respected Contributor

Re: Perl script help required

#!/usr/bin/perl
use strict;
use warnings;

my @lv;
my @lvsize;
my @fs;

open(MYFILE,"xxxxxxxx") #where xxx is file name.
my @fh=;
foreach(@fh) {
my ($lv,$lvsize,$fs)=split(/ /,$_);
push(@lv,$lv);
push(@lvsize,$lvsize);
push(@fs,$fs);
}
print "The following is the lvinfo:\n";
print "@lv\n";
print "The following is the lvsize:\n";
print "@lvsize\n";
print "The following is the fs:\n"
print "@fs\n";

hope this helps.
Hein van den Heuvel
Honored Contributor

Re: Perl script help required

Akram,

There are MANY ways to do this.
The best way depends on the actual problem you are trying to solve.

I suspect you do not really want 3 arrays as suggested but possibly just 2 keyed by the third such that you can use a variable like: $size{'lvappl')

Still, here is an example answerring your question:

$ cat > x
lvdata 20000 /ora/data
lvappl 2048 /ora/appl
lvcs 1024 /ora/scs
lvora 2048 /ora
$ perl -lne '($lv[$.],$size[$.],$fs[$.]) = split}{ print $size[3]' x
1024

what this does is use the implied loop with -n.
Each record is split (on spaces) and the result placed in three (undeclared) array @lv, @size and @fs, using the input file line number as index.

the '}{' (eskimo kiss) closes the implied input loop and opens the end processing which, as an example just prints the size for line 3.

hth,
Hein.


Ralph Grothe
Honored Contributor

Re: Perl script help required

TIMTOWTDI

one possible way:

map {chomp;push @lv,$_->[0];push @sz,$_->[1];push @fs,$_->[2]}
map [m|([-\w]+)\s+(\d+)\s+([-\w./]+)|], ;

__DATA__
lvdata 20000 /ora/data
lvappl 2048 /ora/appl
lvcs 1024 /ora/scs
lvora 2048 /ora
Madness, thy name is system administration
James R. Ferguson
Acclaimed Contributor

Re: Perl script help required

Hi:

For fun, in the spirit of TMTOWTDI, using your data in 'file' as input, the following will print the array of sizes digested:

# perl -nle '@a=split;for ($i=0;$i<=$#a;$i++) {push @{$list{$i}},$a[$i]};END{print "@{$list{1}}"}' file

...returns:

20000 2048 1024 2048

This uses a hash of arrays. Each hash element is keyed by the field number of the split line read.

Regards!

...JRF...

Akram Shaik
Frequent Advisor

Re: Perl script help required

@David ,

I tried your
Global symbol "@fh" requires explicit package name at ./scr4 line 10

@Hein,

as suggested by you I tried the command from command line , well it worked fine.

I guess I need to explain out my requirement a bit more clear,

1. Read the file which contains the data
2. First field will be stored in one array variable, second in another and so on.
3. I should be able to call the array variable @LVNAME say I need $LVNAME[1] whenever required,

Hein , is it possible to call the array @lv,
inside a script.
I dont want to print it as such

Thanks all for your valuable suggestions

regards
Akram








when everyting is coming your way then you are in the wrong lane
Hein van den Heuvel
Honored Contributor

Re: Perl script help required

>>> I tried your
Global symbol "@fh" requires explicit package name at ./scr4 line 10

It's just a minor typo in line 9 (not 10).
A missing semicolon.
There is an other missing semi at a print line around line 20.

> 1. Read the file which contains the data
Done already!
> 2. First field will be stored in one array variable, second in another and so on.
Done already!

> 3. I should be able to call the array variable @LVNAME say I need $LVNAME[1] whenever required,

Done already... with a different name.
@xyz is an array in perl
@xyz[n] is element n in that array.
$xyz[n] is the preferred way to refer to that same element n.

>>> Hein , is it possible to call the array @lv,

Sure... check this...

$ perl -lne '($lv[$i],$size[$i],$fs[$i]) = split; $i++}{ print join qq(\n),@lv' x
lvdata
lvappl
lvcs
lvora


btw.. I replaced $. by a self-maintained $i, in case you need to skip some input lines.

Hein.
Akram Shaik
Frequent Advisor

Re: Perl script help required

Hi
Again all commands work awesome on the command line , and prints the content ,

But I need to add these in script and every field in the file contained an array variable :-( . I am not able to do that with the same options given by all in a script file .

The following does not work

open(DATA,/test3/paramfile)
map {
chomp;
push @lv,$_->[0];
push @sz,$_->[1];
push @fs,$_->[2]
}
map [m|([-\w]+)\s+(\d+)\s+([-\w./]+)|],;
print @lv;
print @sz;
print @fs;

Prints me nothing..

and

open(DATA,/test3/paramfile)
@a=split ;
for($i=0;$i<=$#a;$i++)
{
push @{$list{$i}},$a[$i]};END{print "@{$list{1}}"}

Gives me error of course. Please correct if I am doing something bad.

Thanks again
when everyting is coming your way then you are in the wrong lane
James R. Ferguson
Acclaimed Contributor

Re: Perl script help required

Hi Akram:

Your 'open' statement is incorrect and you are missing semicolons after statements. Re-working the commandline into a script might look like this:

#!/usr/bin/perl
use strict;
use warnings;
my $i;
my @a;
my %list;
my $file = "/test3/paramfile";

open( DATA, "<", $file ) or die "Error: Can't open $file\n";

while () {
@a = split;
for ( $i = 0 ; $i <= $#a ; $i++ ) {
push @{ $list{$i} }, $a[$i];
}
}
print "sizes = @{$list{1}}\n";

...

You should always use the 'strict' and 'warnings' pragma for other than commandline scripts! You will save yourself countless hours of chasing stupid mistakes.

Regards!

...JRF...
James R. Ferguson
Acclaimed Contributor
Solution

Re: Perl script help required

Hi (again) Akram:

By the way, I would limit the use of a file handle named "DATA" or "END" to the file handle for data stored within a script, like Ralph used:

#!/usr/bin/perl
while () {
print;
}
__DATA__
line-1
line-2
line-3

Note the actual datafile delimiter token begins and ends with two underscore ("_") characters whereas the file handle is the simple token DATA.

A common package name for a file handle is FH, so I would have sritten:

...
my $file = "/home/jrf/myfile";
open( FH, "<", $file ) or die "Error: Can't open $file\n";
...

Regards!

...JRF...

Regards!

...JRF...
Hein van den Heuvel
Honored Contributor

Re: Perl script help required

>> But I need to add these in script and every field in the file contained an array variable :-( .

Array in a shell script calling perl, or just an array in perl?

Of course I agree 100% with FRF that for anything beyond a one-liner, you need to do perl 'properly' making things slear, and obvious and checked.

My simple command line, but now as script might looks like:


#!/usr/bin/perl
use strict;
use warnings;
my (@lv, @size, @fs);
my $i=0;
#
# Read in all data lines from STDIN or first file mentioned.
#
while (<>) {
($lv[$i], $size[$i], $fs[$i]) = split;
$i++;
}
#
# Now all data is in the arrays.
# Let's prove we can use it there with
# a silly exercise to report object in order of descending size.
#
foreach $i (sort { $size[$b] <=> $size[$a] } 0..@size-1) {
printf qq(%d, %9d %-10s %-20s\n), $i, $size[$i], $lv[$i], $fs[$i];
}

0..@size-1 : this generates a list from 0 to the size of the array minus one, this iterting over all elements.

Yes, I could alsso have written:
my $max_elements = @size - 1;
or even exploit the fact tht we counted in $i:
my $max_elements = --$i;


sort {xxx} : sort using function described with xxx, where $a and $b are available as the things to compare
foreach $i (sort { $size[$b] <=> $size[$a] }

Here xxx : $size[$b] <=> $size[$a]
So it does not compare the element numbers, but the value of the array elements pointed to.

Clear as mud?
Cheers,
Hein.

Akram Shaik
Frequent Advisor

Re: Perl script help required

Hi James ,

Your re worked script display the following

sizes = 20000 2048 1024 2048

But what I am looking for is :

How will I print/call the value 20000 only or 2048 only ,

when everyting is coming your way then you are in the wrong lane
James R. Ferguson
Acclaimed Contributor

Re: Perl script help required

Hi (again) Akram:

> How will I print/call the value 20000 only or 2048 only?

Searching for something is often best solved with a hash (or an "associative array" if you are accustomed to thinking in 'awk'). Consider:

# cat ./findit
#!/usr/bin/perl
use strict;
use warnings;
my ( $i, $size );
my @a;
my %list;
die "Usage: $0 size file\n" unless $#ARGV+1 >= 2;
$size = shift;
while (<>) {
@a = split;
push @{ $list{ $a[1] } }, $a[0] . ":" . $a[2];
}
print "size = $size:\n";
print "\t$_\n" for @{ $list{$size} };
1;

...Using your original file as data, do:

# ./findit 2048 myfile
size = 2048:
lvappl:/ora/appl
lvora:/ora

# ./findit 20000 myfile
size = 20000:
lvdata:/ora/data

Regards!

...JRF...
Akram Shaik
Frequent Advisor

Re: Perl script help required

@ All,

Thanks for your overwhelming response ,

with your inputs I managed to extract data from the file. I see there are numerous ways to perform a single task in Perl especcially.

I used James script to perform my task.

Heins is also very similar but contains some added info , Will come in handy in future too.

I am new to perl. Are there any documented material for perl especially for generating
reports extracting data from file etc

Am sure this will get into my brain by practice and doing more of scripting only.

Regards,
Akram
when everyting is coming your way then you are in the wrong lane