Sorry I wasn't so clear. Let me go into a little more detail on what I’m trying to accomplish. The @list is coming from a file handler that returns a list from a sys. command. The length varies is so I’m just cycling through it in while statement. In a nut shell all I’m doing is looking to see if all the elements are present in the new "@list" and let the user know which elements are missing.
open($syscmd,"ps -a |") || die "unable to open system command $!\n";
$count =0;
while (<$syscmd>){
@list1 = split(" ", $_);
@list[$count] = @list1[3];
$count = $count + 1;
}
$set = 0;
foreach $val(sort keys(%prolist)){ #checks through every element
+in the hash one by one.
while(<@list>){ #looks through each element in list for a matc
+h
if ($prolist{$val} eq $_ ){ #if the match is found
$set = 1; #sets this to true so that the below if sta
+tment isn't executed
last; }
}
if ($set == 0){ #prints only if there is no match print
+ "NF: $prolist{$val}\n";
}
$set = 0; #resets boolen
}
| [reply] [d/l] |
you read all the lines from a file handle ($syscmd) and take the third column of each and put this in @list. You then want to see which elements of a second list are NOT in @list.
Here's how i'd do it: just remove from %pro all of the elements in @list.
# the values here don't matter, all we really
# care about is the existence of the keys
my %pro = map { $_, 1 }
qw[CMD /bin/sh rds SysExec /oasis/bin/sysmenu
/oasis/bin/TS_TextSrvcs];
# get the third column from every line of $syscmd
my @list = map { (split " ")[3] } <$syscmd>;
# remove the keys of %pro in @list
delete @pro{@list};
# print the error message
foreach my $not_found (keys %pro) {
print "Didn't find $not_found in output of system cmd.\n";
}
| [reply] [d/l] [select] |
OK, that's a lot clearer. The basic thing you're doing wrong is using angle brackets to go through a list, which is not necessary. The angle brackets are generally associated with doing I/O.
But you're also doing a lot of unnecessary work, like the way you're counting up the number of items you're pushing into your list. Perl has constructs for doing that kind of stuff much more easily; you can even do it in one line, like this:
push @list, (split ' ')[3] foreach <$syscmd>;In case that's too compact, here's the equivalent broken up a little more:
while (<$syscmd>)
{
my @temp = split ' ';
push @list, $temp[3];
}
Of course, this also takes up more space, for the temporary array.
Your main loop searches an array for a matching element. That's a common enough construct that perl has a special construct for it, the grep function. Here's how you'd use it in this context:
foreach my $val (sort keys %prolist)
{
unless (grep($prolist{$val} eq $_))
{
print "NF: $prolist{$val}\n";
}
}
There are ways to tighten up that loop, but this lets you see what's going on. Your original code can be fixed by just taking out the angle brackets in the while, but you may as well pick up some perl nifty tricks while you're at it.
(BTW, I haven't tested any of this code.)
| [reply] [d/l] [select] |
While the use of the angle brackets here is strange and unnecessary, I don't see how it breaks the original code. I tried it, and it works fine with Perl 5.6.1. I thought that maybe the while on <@list> would maybe only work once; i.e.; the first end-of-list would behave like and EOF and have to be reset somehow. But that's not the case in my tests.
my @x = (qw/a b c abc def ghi z/);
while (<@x>)
{
print "<$_>\n";
}
print "\n\n";
while (<@x>)
{
print "<$_>\n";
}
<a>
<b>
<c>
<abc>
<def>
<ghi>
<z>
<a>
<b>
<c>
<abc>
<def>
<ghi>
<z>
| [reply] [d/l] [select] |