open for pipe problem

V

Vahid

Hi,
I have the following code:
#!/bin/perl -w
#
open(myFILE, "| awk -F: 's[$1]++==0' "); # this line does not work
# open(myFILE, "| sort -t : -nu -k 3,3"); # this line works fine
open(DB, "passwd");
while (<DB>) { print myFILE; }
close(myFILE);

When I run it, I get this error:
Use of uninitialized value in concatenation (.) or string at
../perl_awk.pl line 3.
awk: syntax error near line 1
awk: bailing out near line 1

Can someone help me debug this if possible?
Thanks.
 
I

Ian Wilson

Vahid said:
Hi,
I have the following code:
#!/bin/perl -w

use strict;
#
open(myFILE, "| awk -F: 's[$1]++==0' "); # this line does not work

or die "unable to open a pipe to awk because $!";
# open(myFILE, "| sort -t : -nu -k 3,3"); # this line works fine
open(DB, "passwd");

or die "unable to open 'passwd' because $!";
while (<DB>) { print myFILE; }
close(myFILE);

When I run it, I get this error:
Use of uninitialized value in concatenation (.) or string at
./perl_awk.pl line 3.

Because you have " ... $1 ... " and perl interpolates variables into
double-quoted strings. Try using single quotes.
awk: syntax error near line 1
awk: bailing out near line 1

Probably because perl interpolated nothing for $1.

I'd use lexical filehandles (open my $db, 'passwd' or die ...)

I would rewrite the AWK expression in Perl to save having to start up a
separate process in a different programming language. I'd avoid solving
a trivial task using a mixture of two languages.
 
B

Brian McCauley

Vahid said:
Hi,
I have the following code:

Written in Perl4?

May I suggest that if you are just starting to learn Perl now you start
with Perl5.8 and don't worry much about writing code that'll run on
Perl4. Perl5 has a lot of advancements that'll make programminng a lot
easier.
#!/bin/perl -w
#
open(myFILE, "| awk -F: 's[$1]++==0' "); # this line does not work

Double-quoted strings in Perl interpolate Perl variables.
Use of uninitialized value in concatenation (.) or string at
./perl_awk.pl line 3.
awk: syntax error near line 1
awk: bailing out near line 1

Yes the Perl variable $1 is undefined so Perl gives a warning and awk
gives and error when it tries to compile 's[]++==0'

You can fix this in a number of ways.

open(myFILE, q{| awk -F: 's[$1]++==0' } ) or die $!;
open(myFILE, '|-','awk','-F:','s[$1]++==0' ) or die $!; # The best
open(myFILE, "| awk -F: 's[\$1]++==0' " ) or die $!;
open(myFILE, '| awk -F: \'s[$1]++==0\' ' ) or die $!;

You'll note I've appended "or die" after the open. You should get into
the habit of doing this whenever you can't be bothered to do something
more intelegent with the return value of open().

Of course haning a Perl script call awk in this way doesn't make sense,
much simpler to do whatever is is you want in Perl.
Can someone help me debug this if possible?

Yes, the way to have debuggged it would have been to try printing out
the string you were constructing.

print "| awk -F: 's[$1]++==0' ";

This is a very general piece of advise. When any function in any
language is not doing what you exected try printing out the arguments
to are passing to it to see if they really are what you intended.
 
B

Brian McCauley

Ian said:
or die "unable to open 'passwd' because $!";
I'd use lexical filehandles (open my $db, 'passwd' or die ...)

I'd also use the 3-argument open() . IMNSHO the 2-argument open is
even more out-dated than bareword filehandles.

open my $db, '<','passwd' or die $!;
 
B

Brian McCauley

Ian said:
or die "unable to open 'passwd' because $!";
I'd use lexical filehandles (open my $db, 'passwd' or die ...)

I'd also use the 3-argument open() . IMNSHO the 2-argument open is
even more out-dated than bareword filehandles.

open my $db, '<','passwd' or die $!;
 
V

Vahid

Brian said:
Written in Perl4?
# perl -v
This is perl, v5.8.0 built for sun4-solaris
....
You can fix this in a number of ways.

open(myFILE, q{| awk -F: 's[$1]++==0' } ) or die $!;
open(myFILE, '|-','awk','-F:','s[$1]++==0' ) or die $!; # The best
open(myFILE, "| awk -F: 's[\$1]++==0' " ) or die $!;
open(myFILE, '| awk -F: \'s[$1]++==0\' ' ) or die $!;

Thanks Brian, the line that you marked as the best works fine, I
started writing a native
perl sub but I need something quick and dirty. I will try to convert it
to perl later.
You'll note I've appended "or die" after the open. You should get into
the habit of doing this whenever you can't be bothered to do something
I will. thanks again.
Vahid.
 
P

Paul Lalli

Vahid said:
# perl -v
This is perl, v5.8.0 built for sun4-solaris
...

Brian meant that your coding style is much more consistent with the
Perl 4 language. Even though modern Perl's are (mostly)
backwards-compatable, it would be a good idea to take advantage of the
recent features that make programs both better looking and easier to
maintain.

You can fix this in a number of ways.

open(myFILE, q{| awk -F: 's[$1]++==0' } ) or die $!;
open(myFILE, '|-','awk','-F:','s[$1]++==0' ) or die $!; # The best
open(myFILE, "| awk -F: 's[\$1]++==0' " ) or die $!;
open(myFILE, '| awk -F: \'s[$1]++==0\' ' ) or die $!;

Thanks Brian, the line that you marked as the best works fine, I
started writing a native
perl sub but I need something quick and dirty. I will try to convert it
to perl later.

If I understand your awk arguments, you're trying to print out the
lines that contain the first instance of each possible first field
(where fields are separated by colons). Is this correct? So for the
following test file:
foo:bar:baz
dayo:eek:kay:done
foo:blah:dayo
foo:perl:awk
perl:sed:awk
awk:c:c++

you would want to print out:
foo:bar:baz
dayo:eek:kay:done
perl:sed:awk
awk:c:c++

This can be fairly straightforwardly converted to Perl:

perl -na -F: -e'print if $s{$F[0]}++==0'

And indeed, using the sample data above, both my perl line and your awk
line print the same results.

for more information, look at the various options (-n, -a, and -F) in
perldoc perlrun

Paul Lalli
 
V

Vahid

Paul said:
Brian meant that your coding style is much more consistent with the
Perl 4 language. Even though modern Perl's are (mostly)
backwards-compatable, it would be a good idea to take advantage of the
recent features that make programs both better looking and easier to
maintain. Sorry and thanks.


If I understand your awk arguments, you're trying to print out the
lines that contain the first instance of each possible first field Yes, you are correct.

This can be fairly straightforwardly converted to Perl:

perl -na -F: -e'print if $s{$F[0]}++==0'

perldoc perlrun
I tested your line too and got the same result as Brian's, I will
consider changing awk to perl (5) style.
Paul Lalli
Thanks Paul.
 
B

Brian McCauley

Ian said:
or die "unable to open 'passwd' because $!";
I'd use lexical filehandles (open my $db, 'passwd' or die ...)

I'd also use the 3-argument open() . IMNSHO the 2-argument open is
even more out-dated than bareword filehandles.

open my $db, '<','passwd' or die $!;
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top