String and Array Programming in Perl

D

DeveloperGuy

I am very very new to Perl and am trying automate a process in my AIX
Unix box. I issed the command ps -aef and sent it to a file. How do
I get how many different users running programs, the total time for
each user in hours:minutes format, and who is running the longest
process and the program name? I am not familiar with using the loops.
I know that I can probably use the date command to specify the date.
This is where I am stuck thus far. Please help anyone...

#! /usr/bin/perl

use strict;
use warnings;

@users;
@tmpfile = OPEN(DataFileHandle, /home/smallp/data.txt);

$tmpfile[0];
$users[0];

for ($count= 0; $count <= $#users; $count++;) {
If $tmpline[0] eq $users
if TRUE then exit
push(@users, $users[0]);
}
 
T

Tad McClellan

DeveloperGuy said:
I am very very new to Perl


We will still expect that you use Perl rather than something
merely Perlish-looking.

and am trying automate a process in my AIX
Unix box. I issed the command ps -aef and sent it to a file.


You can do that from within Perl itself, no need for a file.

my @ps_lines = `ps -aef`; # backwards single quotes
or
my @ps_lines = qx/ps -aef/; # backwards single quotes in disguise
or
open PS, 'ps -aef|' or die "could not run ps $!";
How do
I get how many different users running programs, the total time for
each user in hours:minutes format, and who is running the longest
process and the program name?


By parsing the output of the ps command.

You might want to use Perl's unpack() or substr() functions
to help you with that.

I am not familiar with using the loops.


Then become familiar with using the loops, they are documented in:

perldoc perlsyn

I know that I can probably use the date command to specify the date.


You can do that from within Perl too, no need for an external date program.

perldoc -f localtime
perldoc -f gmtime

This is where I am stuck thus far. Please help anyone...

#! /usr/bin/perl

use strict;


When you put that in your programs you are making a promise:

I promise to declare my variables before using their short names.

If you break your promise, then perl will refuse to run your program.

use warnings;

@users;


You have not declared that variable, so perl refuses to run your program.

my @users;

@tmpfile = OPEN(DataFileHandle, /home/smallp/data.txt);


Perl does not have an OPEN() function, only an open() function.

Case matters.

Put 'quotes' around your strings.

open() returns a single thing, no need for an array to hold its return value.

It is a convention to use all UPPER CASE for filehandles.

You should always, yes *always*, check the return value from open()
to ensure that you actually got what you asked for:

open DATA_FILEHANDLE, '/home/smallp/data.txt' or
die "could not open '/home/smallp/data.txt' $!";


Your code never makes use of the filehandle. You will need to *read*
from it to get the data to process...

$tmpfile[0];
$users[0];


Those are do-nothing statements, they have no useful effect.

What were you hoping those 2 lines of code would do for you?

for ($count= 0; $count <= $#users; $count++;) {


A more Perlish way to get the same thing is:

foreach my $count ( 0 .. $#users ) {

If $tmpline[0] eq $users



Perl does not have an "If" keyword, only an "if" keyword.

Case (still) matters.

You need (parenthesis) around the condition in an if statement.

if TRUE then exit


Perl does not even have a "then" keyword, nor a "TRUE" keyword.

This is not Perl code. What language is it?
 
A

A. Sinan Unur

I am very very new to Perl and am trying automate a process in my AIX
Unix box. I issed the command ps -aef and sent it to a file. How do
I get how many different users running programs, the total time for
each user in hours:minutes format, and who is running the longest
process and the program name? I am not familiar with using the loops.
I know that I can probably use the date command to specify the date.
This is where I am stuck thus far. Please help anyone...

This means you need to bite the bullet and actually pay for a book. For
recommendations, go to http://learn.perl.org/

Now:
#! /usr/bin/perl

use strict;
use warnings;

Good :)

Not good:

D:\Home> perl -c t.pl
Bareword found where operator expected at t.pl line 7, near "/home/smallp"
(Missing operator before allp?)
Global symbol "@users" requires explicit package name at t.pl line 6.
Global symbol "@tmpfile" requires explicit package name at t.pl line 7.
syntax error at t.pl line 7, near "/home/smallp"
Global symbol "@tmpfile" requires explicit package name at t.pl line 9.
Global symbol "@users" requires explicit package name at t.pl line 10.
Global symbol "$count" requires explicit package name at t.pl line 12.
Global symbol "$count" requires explicit package name at t.pl line 12.
Global symbol "@users" requires explicit package name at t.pl line 12.
Global symbol "$count" requires explicit package name at t.pl line 12.
syntax error at t.pl line 12, near "++;"
t.pl has too many errors.

Why did you not fix this stuff before posting?
@tmpfile = OPEN(DataFileHandle, /home/smallp/data.txt);

perldoc -f open

I think it was Tad who put it most eloquently: You can't just make s**t up
and expect it to work!
$tmpfile[0];
$users[0];
Huh?

for ($count= 0; $count <= $#users; $count++;) {
If $tmpline[0] eq $users
if TRUE then exit
Huh???

push(@users, $users[0]);
}


I guess I'll take the bait anyway.

I have:

D:\Home> ps -v
PS (cygwin) 1.11
Process Statistics
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
Compiled on May 25 2004

and I get:

D:\Home> ps -aef
UID PID PPID TTY STIME COMMAND
hbb1 582167 1 con 16:09:39 /usr/bin/BASH
hbb1 565087 1 con 16:09:52 /usr/bin/PS

#! /usr/bin/perl

use strict;
use warnings;

my $name = 'd:/home/data.txt';

open my $file, '<', $name
or die "Cannot open $name: $!";

<$file>; # assuming first line is header, so skip it

my $ps;

while(<$file>) {
chomp;
s/^\s*//g; # skip lines with whitespace only
next unless length $_;
my ($uid, $pid, $ppid, $tty, $stime, $command) = split;

$ps->{$pid} = {
uid => $uid,
ppid => $ppid,
tty => $tty,
stime => $stime,
command => $command,
};
}

use Data::Dumper;
print Dumper $ps;
__END__

Output:

D:\Home> perl t.pl
$VAR1 = {
'565087' => {
'uid' => 'hbb1',
'ppid' => '1',
'command' => '/usr/bin/PS',
'stime' => '16:09:52',
'tty' => 'con'
},
'582167' => {
'uid' => 'hbb1',
'ppid' => '1',
'command' => '/usr/bin/BASH',
'stime' => '16:09:39',
'tty' => 'con'
}
};
 
A

Anno Siegel

A. Sinan Unur said:
I think it was Tad who put it most eloquently: You can't just make s**t up
and expect it to work!

I've always heard it attributed to MJD, though the quote as I know it
also contains the word "retardo".

Anno
 
T

Tad McClellan

Anno Siegel said:
I've always heard it attributed to MJD, though the quote as I know it
also contains the word "retardo".


That's how I found the link I posted, I googled for "retardo perl".

:)
 
D

David K. Wall

Tad McClellan said:
That's how I found the link I posted, I googled for "retardo
perl".

:)

I remembered the phrase, "The error mesage is GOD", seeing a clip of
MJD *screaming* it, and that he had posted his list of Good Advice to
usenet. From the Google usenet archive:

http://groups.google.com/[email protected]

"Of course it doesn't work! That's because you don't know what you
are doing!"

(Sounds like some of my programs.)
 
K

krakle

I am very very new to Perl and am trying automate a process in my AIX
Unix box. I issed the command ps -aef and sent it to a file. How do
I get how many different users running programs, the total time for
each user in hours:minutes format, and who is running the longest
process and the program name? I am not familiar with using the loops.
I know that I can probably use the date command to specify the date.
This is where I am stuck thus far. Please help anyone...

#! /usr/bin/perl

use strict;
use warnings;

@users;
@tmpfile = OPEN(DataFileHandle, /home/smallp/data.txt);

$tmpfile[0];
$users[0];

for ($count= 0; $count <= $#users; $count++;) {
If $tmpline[0] eq $users
if TRUE then exit
push(@users, $users[0]);
}


This isn't Perl this is SHIT... You must NOT of read anything at
all... Pick up a book or read a tutorial or the manpages.. I'm not
even going to rewrite this crap...
 
D

DeveloperGuy

I am very very new to Perl and am trying automate a process in my AIX
Unix box. I issed the command ps -aef and sent it to a file. How do
I get how many different users running programs, the total time for
each user in hours:minutes format, and who is running the longest
process and the program name? I am not familiar with using the loops.
I know that I can probably use the date command to specify the date.
This is where I am stuck thus far. Please help anyone...

#! /usr/bin/perl

use strict;
use warnings;

@users;
@tmpfile = OPEN(DataFileHandle, /home/smallp/data.txt);

$tmpfile[0];
$users[0];

for ($count= 0; $count <= $#users; $count++;) {
If $tmpline[0] eq $users
if TRUE then exit
push(@users, $users[0]);
}




Okay, I finally got the script to read the file.

#! /usr/bin/perl
#This program reads a file based on the command ps -aef called data.txt
#and the following questions have to be answered
#how many users are running programs?
#what is the total time used by each user in hours: minutes?
#who is running the longest process, list user, time and name of program
#use strict;
#use warnings;

open(DataFileHandle, "/home/smallp/data.txt");

@tmpfile = <DataFileHandle>;
@users;
$users[0];

foreach $i (@tmpfile)
{
print "$i\n";
}
close DataFileHandle;
 
D

DeveloperGuy

I have looked in the online sections you have recommended but what is
wrong with the script? What is wrong with push commands and how can I
answer the following from the ps-aef command?
#and the following questions have to be answered
#how many users are running programs?
#what is the total time used by each user in hours: minutes?
#who is running the longest process, list user, time and name of
program

#! /usr/bin/perl



open PS, "data.txt" or die "could not open file $!";
my @tmpline;



foreach $i (<data.txt>) {
my @users = @tmpline;
if @tmpline[0] != @users
push my @users, $_;

}



Tad McClellan said:
DeveloperGuy said:
I am very very new to Perl


We will still expect that you use Perl rather than something
merely Perlish-looking.

and am trying automate a process in my AIX
Unix box. I issed the command ps -aef and sent it to a file.


You can do that from within Perl itself, no need for a file.

my @ps_lines = `ps -aef`; # backwards single quotes
or
my @ps_lines = qx/ps -aef/; # backwards single quotes in disguise
or
open PS, 'ps -aef|' or die "could not run ps $!";
How do
I get how many different users running programs, the total time for
each user in hours:minutes format, and who is running the longest
process and the program name?


By parsing the output of the ps command.

You might want to use Perl's unpack() or substr() functions
to help you with that.

I am not familiar with using the loops.


Then become familiar with using the loops, they are documented in:

perldoc perlsyn

I know that I can probably use the date command to specify the date.


You can do that from within Perl too, no need for an external date program.

perldoc -f localtime
perldoc -f gmtime

This is where I am stuck thus far. Please help anyone...

#! /usr/bin/perl

use strict;


When you put that in your programs you are making a promise:

I promise to declare my variables before using their short names.

If you break your promise, then perl will refuse to run your program.

use warnings;

@users;


You have not declared that variable, so perl refuses to run your program.

my @users;

@tmpfile = OPEN(DataFileHandle, /home/smallp/data.txt);


Perl does not have an OPEN() function, only an open() function.

Case matters.

Put 'quotes' around your strings.

open() returns a single thing, no need for an array to hold its return value.

It is a convention to use all UPPER CASE for filehandles.

You should always, yes *always*, check the return value from open()
to ensure that you actually got what you asked for:

open DATA_FILEHANDLE, '/home/smallp/data.txt' or
die "could not open '/home/smallp/data.txt' $!";


Your code never makes use of the filehandle. You will need to *read*
from it to get the data to process...

$tmpfile[0];
$users[0];


Those are do-nothing statements, they have no useful effect.

What were you hoping those 2 lines of code would do for you?

for ($count= 0; $count <= $#users; $count++;) {


A more Perlish way to get the same thing is:

foreach my $count ( 0 .. $#users ) {

If $tmpline[0] eq $users



Perl does not have an "If" keyword, only an "if" keyword.

Case (still) matters.

You need (parenthesis) around the condition in an if statement.

if TRUE then exit


Perl does not even have a "then" keyword, nor a "TRUE" keyword.

This is not Perl code. What language is it?
 
B

Brian McCauley

DeveloperGuy rudely vomits TOFU in our faces:

[ TOFU corrected ]
I have looked in the online sections you have recommended but what is
wrong with the script?

Like Tad said, it is not writen in Perl.

Before asking human beings to help you should first get all the help you
can from your computer. Put

use strict;
use warnings;

at the top and fix _all_ the mistakes Perl tells you about.

Only then ask humans to help.

Do not post TOFU. It is very rude. When you are very rude then people
will be less likely to want to help you.

What is wrong with push commands and how can I
answer the following from the ps-aef command?
#and the following questions have to be answered
#how many users are running programs?
#what is the total time used by each user in hours: minutes?
#who is running the longest process, list user, time and name of
program

#! /usr/bin/perl



open PS, "data.txt" or die "could not open file $!";
my @tmpline;



foreach $i (<data.txt>) {
my @users = @tmpline;
if @tmpline[0] != @users
push my @users, $_;


That is not the syntax of the Perl if statement.


The syntax of the Perl if statement can be found in the 'perlsyn' manual.

http://search.cpan.org/~nwclark/perl-5.8.5/pod/perlsyn.pod#Compound_Statements

There appart from that there are many mistakes Perl would tell you about
if you let it.
 
W

Whitey Johnson

Okay, I finally got the script to read the file.

#! /usr/bin/perl
open(DataFileHandle, "/home/smallp/data.txt");

@tmpfile = <DataFileHandle>;
@users;
$users[0];

foreach $i (@tmpfile)
{
print "$i\n";
}
close DataFileHandle;

I am kinda new to Perl myself but wouldn't it be quicker to do it this way:
----
my @pslist = `ps -aux`;

foreach (@pslist) {
print "$_\n";
}
 
T

Tad McClellan

Whitey Johnson said:
my @pslist = `ps -aux`;
foreach (@pslist) {

That way you don't have to worry about running ps from the command line
you can get a new output from it everytime you run your script.


You don't need the @pslist temporary variable either:

foreach ( `ps -aux` ) {
 
T

Tad McClellan

DeveloperGuy said:
I have looked in the online sections you have recommended but what is
wrong with the script?


It is not written in the Perl programming language, for a start.

open PS, "data.txt" or die "could not open file $!";
foreach $i (<data.txt>) {
^^^^^^^^

That is not a filehandle, you need a filehandle for the input operator.


if @tmpline[0] != @users


Perl requires parenthesis around the condition.

Since your code does not have any parenthesis around the condition,
it is not written in Perl.

We cannot help troubleshoot code in other languages.

Sorry.



[ snip 140 lines that didn't need to be there.

DO NOT TOP-POST!

Find out what that is and how to not do it.

Top-post one more time and all of your posts will become
invisible to me forevermore.
]
 
K

krakle

Okay, I finally got the script to read the file.

We'll see...
#! /usr/bin/perl

Where's the -w switch?

#!/usr/bin/perl -w
#bunch of comments here blah blah blah
#use strict;
#use warnings;

Why use those pragmas if you aren't going to USE them?

use strict;
use warnings;
open(DataFileHandle, "/home/smallp/data.txt");

What if it doesn't exist? What if it CAN'T open??? Error handle!

open (DataFileHandle, "/home/smallp/data.txt") or die "Can't open
file: $!\n";
@tmpfile = <DataFileHandle>;

Scope your variable!!!

my @tmpfile = <DataFileHandle>;

Now since you have the data in @tmpfile you might as well CLOSE the
file since you ARE done with it so:

close (DataFileHandle);
@users;
$users[0];

USELESS does NOTHING.. Hell, tha @users array isn't even used in this
script... OMIT it..
foreach $i (@tmpfile)

Scope please...

foreach my $i (@tmpfile)
{
print "$i\n";
}

So the final result is:

#!/usr/bin/perl -w

use strict;
use warnings;

open (DataFileHandle, "/home/smallp/data.txt") or die "Can't open
file: $!\n";
my @tmpfile = <DataFileHandle>;
close (DataFileHandle);

foreach my $i (@tmpfile) {
print "$i\n";
}


Or another way...

#!/usr/bin/perl -w

use strict;
use warnings;

open (FILE, "/some/where/file.ext") or die "Can't open file: $!\n";
while (<FILE>) { print "$_\n" }
close (FILE);
 
P

Peter Wyzl

----- Original Message -----
From: "Tad McClellan said:
A more Perlish way to get the same thing is:

foreach my $count ( 0 .. $#users ) {

Even more 'Perlish' would be

for my $count (@users){

# From Perlsyn:
The foreach keyword is actually a synonym for the for keyword, so you can
use foreach for readability or for for brevity.
 
J

Jürgen Exner

Peter said:
Even more 'Perlish' would be
for my $count (@users){

Which on the other hand does a different task.
One loops through the indices of the array, the other loops through the
elements of the array.
Granted, in the vast majority of cases you want the elements, but you never
know....

jue
 
T

Tad McClellan

Peter Wyzl said:
Even more 'Perlish' would be

for my $count (@users){


But that doesn't "get the same thing".

(and you wouldn't call it "count" when it wasn't a count)
 
P

Peter Wyzl

Tad McClellan said:
But that doesn't "get the same thing".

(and you wouldn't call it "count" when it wasn't a count)

True, true. I should have pointed out the difference (thanks Jue as well).
In this case the OP _was_ comparing the elements of the arrays, but I should
have stated that difference as 'a more Perlish way to compare array elements
in a foreach loop would be:'

foreach my $element (@array) {
#compare $element with whatever...
}

would make more sense as you point out.

A less than auspicious return to clpm for me it appears... :(

Sorry about the stealth...

/me takes 2 demerits and goes to the back of the class
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top