I'm just starting to learn Perl today by going through Modern Perl, but one of the examples is tripping me up. The book has this code:
while (<>)
{
chomp;
say scalar reverse;
}
Running this code with the command perl stdin.pm hi.txt or cat hi.txt | perl stdin.pm gives me this error:
syntax error at stdin.pm line 4, near "say scalar"
Execution of stdin.pm aborted due to compilation errors.
The contents of hi.txt are:
hi
how
are
you
What am I doing wrong?
You can enable say feature
use feature `say`;
or use what author of the book suggest,
use Modern::Perl;
Related
I am trying to execute below awk command inside a perl script, but it is failing.
#!/usr/bin/perl
print `awk -F, '{print $NF}' f1.txt > f2.txt`
This is the error:
syntax error at ./MO.pl line 3, near "print"
Execution of ./MO.pl aborted due to compilation errors.
Can anyone please help what I am doing wrong here?
This is a Perl error and has nothing to do with your awk script itself. The error is usually seen when the previous statement doesn't have a semicolon at the end.
Here's a very simple program (which should include use strict; and use warnings;, but I wanted to emulate what you have).
#! /usr/bin/env perl
#
print "Hello, World\n" # Line 4
print "Hello, Back\n"; # Line 5
And the error message is:
syntax error at test.pl line 5, near "print"
Execution of test.pl aborted due to compilation errors.
Note the error is near the print in Line #5, but the error is actually at the end of Line #4 where I'm missing a semicolon.
Running your exact program works on my system (although doesn't quite produce the results you want). I am assuming this isn't your exact program, but instead a simplification of your program. Is there a statement before that print?
Several other things:
You're redirecting your awk output, so there's nothing to print.
Use strict and warnings.
Better to use qx(....) than backticks (grave accent). It's more readable and allows you to do quoted executable in quoted executable.
Watch for Perlisms in your code. The $NF is interpreted by Perl, and without the use strict;, doesn't give you an error. Instead, the print in your Awk statement is a null print which prints the entire line.
Why do you use print if nothing is printing out? You're better off in this position to use system which allows you to put single quotes around your entire statement:
system q(awk -F, '{print $NF}' f1.txt > f2.txt);
This way, $NF doesn't have to be quoted.
Why are you doing Awk in a Perl program? Perl will do anything Awk will do and do it better:
Here's a version of your program using plain ol' Perl:
#! /usr/bin/env perl
use strict;
use warnings;
use autodie;
while ( my $line = <> ) {
my #array = split /\s*,\s*/, $line;
print $array[-1];
}
To run this program:
$ test.pl f1.txt > f2.txt
Yes, it's longer, but half of the program is taken up by pragmas that all Perl programs should use.
I'm sure people smarter than me can turn this into a Perl one-liner.
Since you're redirecting the awk output, there's nothing for perl to print. You might as well use system and the quoting operator q():
system q(awk -F, '{print $NF}' f1.txt > f2.txt)
Or, of course, do it in perl, which saves you from having to spawn a shell and then spawn awk:
open my $in, '<', 'f1.txt';
open my $out, '>', 'f1.txt';
while (<$in>) {
print $out (split " ")[-1], "\n";
}
close $in;
close $out;
If there are more lines in the script, you need a semi-colon at the end of the print statement.
>perl -e '$_ = q(t b[\)sizeof];); s/(t?(\w)(?:\s(\w))?\s(\w)(\[([^\]]+)\]))/eval $1/e'
Bareword found where operator expected at (eval 1) line 1, near ")sizeof"
(Missing operator before sizeof?)
This is legal Perl, then why the error message? I have the latest Perl.
This is an SSCCE ; any one character less and the error message does not appear.
The Perl code is valid, but you are trying to eval a string which is not valid Perl code. When I run this code and swap eval for print, it prints the string:
t b[)sizeof]
Now if I try and run this as Perl code I get:
> perl -we't b[)sizeof]'
Bareword found where operator expected at -e line 1, near ")sizeof"
(Missing operator before sizeof?)
Unquoted string "sizeof" may clash with future reserved word at -e line 1.
syntax error at -e line 1, near "[)"
Execution of -e aborted due to compilation errors.
(You should always use warnings -w, even with one-liners)
This code does exactly what your evaluation is trying to do: It's trying to run that string as Perl code, and it fails because that string is not valid Perl code.
Also you should be careful when using eval, as it can do unexpected and catastrophical things to your computer. Usually, this kind of double evaluation is written using two of the /e modifiers, e.g.:
s/.../.../ee
Which is a bit more convenient than
s/.../eval .../e
I am trying to use the following conventions I have been instructed to use for good/proper/safe Perl code for my "Hello, World!" Program:
use strict;
use warnings;
I have created and successfully run the following "Hello World" program using (Strawberry) Perl 5.12 on my main Windows 7 OS:
!#/usr/bin/perl
use strict;
use warnings;
print "Hello, World!\n";
What I got back, as expected, was "Hello, World!".
What struck me as very odd was that the same program run in terminal on my virtualized Linux Mint 14 OS, using Perl 5.14, produced the following error:
"use" not allowed in expression at /PATH/hello_world.pl line 2, at end of line
syntax error at /PATH/hello_world.pl line 2, near "use strict"
BEGIN not safe after errors--compilation aborted at /PATH/hello_world.pl line 3.
I created other "Hello World" programs subsequently without either the use strict; or use warnings; lines, and also one with the -w, which I had seen in some tutorials, indicating, if I am not mistaken, that warnings would be turned on.
Both of my alternate versions worked properly in that they produced my expected result:
Hello, World!
What I cannot be sure of is if I need the use statements in Perl programs from version 5.14 and up or if it is just fine to write the -w at the end of my first line.
I would like to think that I could use a consistent header, so to speak, in all of my Perl programs, whether they are Windows or Linux, Perl 5.12 or 5.14 or otherwise.
Your image shows that all of your scripts start with !#/usr/bin/perl. This is wrong. It is not a valid she-bang line, it is read as negation ! followed by a comment #. The parsing will continue and with script1.pl perl will execute ! print "Hello world.\n";. This will print Hello world and negate the result of print ... not really useful, but valid perl.
In script2.pl perl sees ! use strict; and this is a compile time error and therefor perl fails and reports the error for the line use strict;.
So if you use correct she-bang lines, all three scripts will work as designed.
Edit (test scripts added):
script1.pl
!#/usr/bin/perl
print "Hello world.\n" ;
Calling perl script1.pl gives
Hello world.
script2.pl
!#/usr/bin/perl
use strict;
use warnings ;
print "Hello world.\n" ;
Calling perl script2.pl gives
"use" not allowed in expression at script2.pl line 3, at end of line
syntax error at script2.pl line 3, near "use strict "
BEGIN not safe after errors--compilation aborted at script2.pl line 4.
Using the correct syntax script3.pl
#!/usr/bin/perl
use strict ;
use warnings ;
print "Hello world.\n" ;
Calling perl script3.pl gives
Hello world.
You did something like
use warnings
use strict;
instead of
use warnings;
use strict;
Actually, I think it might be a line ending issue. You have LF where you should have CR LF or vice-versa. I've seen this cause Perl to think the code starts halfway through the shebang line (e.g. perl use strict;)
As mentioned elsewhere, the code you posted and the code you used is different. You actually used
!use strict;
due to a bad shebang line.
!#/u... # Negation followed by a comment
should be
#!/u... # Shebang
I am writing the following command to extract the text in makefile:-
#awk '/Exported Layer/,/Total Polygons/' out_compare.err | perl -lane '$el=$F[3] if(/Exported Layer/); print "$el: $f[3]" if (/Total Polygons/);' | cat
But it is giving the following error:-
Can't modify constant item in scalar assignment at -e line 1, near "] if"
Execution of -e aborted due to compilation errors.
Would you guys like to suggest something? :-)
Make is oblivious to shell quoting in commands, so the $ characters in your Perl snippet are being interpreted as make variables $e and $F. These variables don't exist in your makefile and are being expanded as empty, leading to the Perl syntax errors you're seeing.
You need to escape the $ characters from make like this:
... perl -lane '$$el=$$F[3] if(/Exported Layer/); ...
See also the GNU Make manual.
When running a perl CGI script in taint mode, I get an error of the form...
Insecure dependency in some_function while running with -T switch at (eval some_line) line some_other_line.
Compilation failed in require at my-script.cgi line 39.
BEGIN failed--compilation aborted at my-script.cgi line 39.
my-script.cgi line 39 is a use statement for a perl module which does not itself use eval or some_function, but presumably uses another library which does. The some_line and some_other_line line numbers don't seem to make sense in either my-script.cgi or the library which is 'use'd on line 39 of my-script.cgi.
Given this error, how can I track down where the taint error is occurring?
I've tried setting a new die signal handler which should print a stack trace, i.e.
$SIG{ __DIE__ } = sub { require Carp; Carp::confess(#_); };
but this seems to have no effect on the error. Perhaps this is the wrong signal to be trapping, not happening early enough, or something more complex is required.
Carp::Always works fine with exceptions raised by taint checks. Example output:
$ perl -MCarp::Always -T blah.pl
Insecure dependency in sprintf while running with -T switch at blah.pl line 6
main::foo() called at blah.pl line 8
main::bar() called at blah.pl line 10
I use Devel::SimpleTrace a lot these days for debugging and it recently helped me find a taint bug when using Archive::Zip.
However, I don't know if it would have worked in your case since it is essentially setting the same sig handler that you used.