Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[q] split in while loop

1 view
Skip to first unread message

Drew Myers

unread,
Dec 14, 2000, 3:53:21 PM12/14/00
to
I am a newbie (and have been for much too long) to perl. I am
attempting to extract information from a log file and format it for a
report.


#!/usr/bin/perl -w

use strict;

my ($file,@data);
my $newestfile=0;
opendir(VMDIR,"/var/adm/vm") || die "Can't open /var/adm/vm: $!\n";
my @vmfilelist = grep !/^\./, sort(readdir(VMDIR));
closedir(VMDIR) || die "Can't close /var/adm/vm: $!\n";
foreach $file(@vmfilelist) {
open(VMFILE, "/var/adm/vm/$file") || die "Can't open $file: $!\n";
while(<VMFILE>) {
next if (/avm/);
my $free = split(" ",$_)[1];
print;
}
}


The log file looks something like this:
memory page faults
avm free si so pi po fr de sr in sy cs
62401 418249 0 0 0 0 0 0 0 74 99 268
CPU
cpu procs
us sy id r b w
24 6 71 1 2 0

I am attempting to grab the number 418249 in this example. The log
file contains multiple occurrences of this type of data, and I want the
number(s) in this same position each time.

The split statement doesn't function (the error states "Can't use
subscript on split"), but I don't understand why.

I know to RTFM but between my Perl books, perldoc (and associated faqs,
etc) I am having trouble determining the solution. Is it a scope
issue? Is it the placement of the split statement itself?

Thanks in advance,
Drew Myers
perotsystems


Sent via Deja.com
http://www.deja.com/

John W. Krahn

unread,
Dec 14, 2000, 4:44:03 PM12/14/00
to
Drew Myers wrote:
>
> I am a newbie (and have been for much too long) to perl. I am
> attempting to extract information from a log file and format it for a
> report.
>
> #!/usr/bin/perl -w
>
> use strict;
>
> my ($file,@data);
> my $newestfile=0;
> opendir(VMDIR,"/var/adm/vm") || die "Can't open /var/adm/vm: $!\n";
> my @vmfilelist = grep !/^\./, sort(readdir(VMDIR));
> closedir(VMDIR) || die "Can't close /var/adm/vm: $!\n";
> foreach $file(@vmfilelist) {
> open(VMFILE, "/var/adm/vm/$file") || die "Can't open $file: $!\n";
> while(<VMFILE>) {
> next if (/avm/);
> my $free = split(" ",$_)[1];

Change this to
my $free = (split(" ",$_))[1];


> print;
> }
> }


John

Dick Latshaw

unread,
Dec 14, 2000, 4:39:07 PM12/14/00
to
In article <91bbvv$dkp$1...@nnrp1.deja.com>,

Drew Myers <bh_...@my-deja.com> wrote:
> my $free = split(" ",$_)[1];

> The log file looks something like this:


> 62401 418249 0 0 0 0 0 0 0 74 99

> I am attempting to grab the number 418249 in this example.

> The split statement doesn't function (the error states "Can't use


> subscript on split"), but I don't understand why.

It's the placement of the parentheses:

my $free = (split(" ",$_))[1];

or, since split splits $_ on space chars by default:

my $free = (split)[1];
--
Regards,
Dick

Stephen Kloder

unread,
Dec 14, 2000, 4:51:47 PM12/14/00
to
Drew Myers wrote:

> I am a newbie (and have been for much too long) to perl. I am
> attempting to extract information from a log file and format it for a
> report.
>
> #!/usr/bin/perl -w
>
> use strict;
>

> <snip earlier code>

> my $free = split(" ",$_)[1];
> print;

the [1] is applied to (" ",$_), sintead of the output of the split
statement. Instead, you should use:
my $free = (split / /)[1];
(use slashes instead of quotes, as quotes can be misleading in split
statements)
BTW, the next statement prints $_, not $free .


>
>
> I know to RTFM but between my Perl books, perldoc (and associated faqs,
> etc) I am having trouble determining the solution. Is it a scope
> issue? Is it the placement of the split statement itself?
>

In this case, you are dealing with precedence issues.
perldoc perlop # Terms and list operators

HTH. HAND.
--
Stephen Kloder | "I say what it occurs to me to say.
step...@cc.gatech.edu | More I cannot say."
Phone 404-874-6584 | -- The Man in the Shack
ICQ #65153895 | be :- think.


Garry Williams

unread,
Dec 14, 2000, 8:39:28 PM12/14/00
to
On Thu, 14 Dec 2000 16:51:47 -0500, Stephen Kloder
<step...@cc.gatech.edu> wrote:

>Drew Myers wrote:
>
>> my $free = split(" ",$_)[1];
>
>the [1] is applied to (" ",$_), sintead of the output of the split
>statement. Instead, you should use:
>my $free = (split / /)[1];
>(use slashes instead of quotes, as quotes can be misleading in split
>statements)

Quotes are not misleading in the first parameter to split(). The use
of quotes is documented in the perlfunc manual page:

split /PATTERN/,EXPR,LIMIT
...
The pattern `/PATTERN/' may be replaced with an expression to
specify patterns that vary at runtime.

There is a semantic difference between

split / /

and

split " "

The default pattern for split is C<' '>. That's quote-space-quote --
not slash-space-slash. That is treated by split() as a _special_
_case_. Here's the quote from the perlfunc manual page:

As a special case, specifying a PATTERN of space (`' '') will split on
white space just as `split' with no arguments does. Thus, `split(' ')'
can be used to emulate awk's default behavior, whereas `split(/ /)' will
give you as many null initial fields as there are leading spaces. A
`split' on `/\s+/' is like a `split(' ')' except that any leading
whitespace produces a null first field. A `split' with no arguments
really does a `split(' ', $_)' internally.

The original poster presumably wants the "awk" behavior because he
wrote `split(" ",$_)' which has the same meaning as `split' or `split
" "', but has a different meaning than `split / /'.

--
Garry Williams

Drew Myers

unread,
Dec 15, 2000, 10:13:50 AM12/15/00
to
Ok,

That solved the split issue. The second problem I'm having. It seems
that the line:

next if (/avm/) {
$free = (split)[1];
print $free;
}

matches the string avm, which is what I want. The output from the
print statement prints everything except the line with "avm". How do I
match just the second field of the following line?

The log looks like:


avm free si so pi po fr de sr in sy cs
62401 418249 0 0 0 0 0 0 0 74 99 268

CPU
cpu procs
us sy id r b w
24 6 71 1 2 0

I only want the 418249, but I get everything except the avm line. Any
suggestions?

Thanks for your patience!


--
Drew Myers
perotsystems

Abe Timmerman

unread,
Dec 16, 2000, 7:59:30 AM12/16/00
to
On Fri, 15 Dec 2000 15:13:50 GMT, Drew Myers <bh_...@my-deja.com> wrote:

> Ok,
>
> That solved the split issue. The second problem I'm having. It seems
> that the line:
>
> next if (/avm/) {
> $free = (split)[1];
> print $free;
> }

That doesn't compile.



> matches the string avm, which is what I want. The output from the
> print statement prints everything except the line with "avm". How do I
> match just the second field of the following line?

Make it read the next line explicitly whenever it finds a line with
'avm'.

#!/usr/bin/perl -w
use strict;

while ( <DATA> ) {
if ( /avm/ ) {
my $free = (split ' ', <DATA>)[1];
print "Free: $free\n";
}
}

__DATA__


avm free si so pi po fr de sr in sy cs
62401 418249 0 0 0 0 0 0 0 74 99 268

CPU
cpu procs
us sy id r b w
24 6 71 1 2 0

--
Good luck,
Abe
perl -wle '$_=q@Just\@another\@Perl\@hacker@;print qq@\@{[split/\@/]}@'

0 new messages