Closed oodler577 closed 1 month ago
@briandfoy might also have more insight. ty!
Why would you expect an error? The -e and -E options take code, not a filename, and 'foo.pl' is a valid Perl script with no strict or warnings enabled. (It creates two strings and concatenates them)
See https://perldoc.perl.org/perlrun#-e-commandline
If -e is given, Perl will not look for a filename in the argument list.
Well, it seems it allowed for a false positive code test to slip through in the aforementioned book; I am assuming they tested to code in the book. Maybe it should be an error. It was surprising.
While the first edition of that book is as old as the oldest version of that documentation I can find (linked below), there is no reasonable way to make that an error because most valid perl code can be a file path and most filepaths will be valid perl code. I can only assume it is an error in the book.
It is an error in that book. If they tested the code, there was no way to detect that was an error - even now. That's the problem. If there is a way to differentiate that from code, then it should throw an error. That's purpose of this issue. Is it a bug with -e
or -E
, or is it just a potential edge case that should be detected? Can it even be detected?
Note,
shell# echo > bin/foo.pl
shell# perl -e bin/foo.pl
Illegal division by zero at -e line 1.
shell# echo $?
255
shell# cd bin
shell# perl -e ./foo.pl
syntax error at -e line 1, near "."
Search pattern not terminated at -e line 1.
shell# echo $?
255
shell# perl -E ./foo.pl
syntax error at -e line 1, near "."
Search pattern not terminated at -e line 1.
shell# echo $?
255
shell# perl -e foo.pl
shell# echo $?
0
shell# perl -E foo.pl
shell# echo $?
0
I understand the error state is due to it being taken as literal Perl code; at least it fails if there is a forward slash (albeit it in at least 2 ways). With no file path separator, it doesn't even fail. False positive and I suspect the root cause of the "bug" in the book's code. Maybe if the code looks like a file path (even with out a leading ./
) there should be a check to see if the file exists, if not fall back to the existing syntax error.
It'll fail if there is a leading .
- again, not for the right reason, but at least it fails.
shell# mv foo.pl .foo.pl
shell# perl -E .foo.pl
syntax error at -e line 1, near "."
Execution of -e aborted due to compilation errors.
shell# echo $?
255
Maybe provide a warning?
Maybe if the code looks like a file path
All code looks like a file path. use strict; use warnings; print "Hello, world!\n"
is a valid filename on Linux.
Can you explain what exactly you want perl to do to detect this case? Because I don't see a way to change anything without breaking the existing documented behavior of perl in other cases.
Maybe provide a warning?
You explicitly did not enable warnings. If you had:
$ perl -we file.pl
Unquoted string "file" may clash with future reserved word at -e line 1.
Unquoted string "pl" may clash with future reserved word at -e line 1.
Useless use of a constant ("filepl") in void context at -e line 1.
I see now. When running perl -e FILE.pl
, we observed that the instructions in the program FILE.pl
did not execute, and assumed that program contained in the file FILE.pl
was being read and somehow run incorrectly due to -e
.
The -w
option clued me in, and allowed me to read everyone's reply to this issue differently than I had been reading them. The -e
option (just as documented) does stop Perl from looking for a file-full-of-code, and looks for code to execute from the rest of the command-line. Without -w
, Perl is in "poetry mode", and happily processes what we think of as a filename, as if it were code.
In this light, I see that perl -e FILE.pl
should produce the same result as:
$ cat > realfile.pl
FILE.pl
^D
$ perl realfile.pl
and it does exactly that. Both produce exactly the same nothing. No warnings are appropriate because we did not say -we
or -wE
as we should have.
I still think the lines from the book are misleading to the point of being erroneous, but this -e
behavior is not the bug in Perl that we thought it was.
I am just reporting it. Seems like a rather special case to consider, especially since it's forever preserved in the 2nd edition of Effective Perl Programming, page 13. And someone typing it is is left perplexed about why it did nothing visible, yet returned $?
of 0
- but was expecting the file to be run. That's all I got.
I still think the lines from the book are misleading to the point of being erroneous, but this -e behavior is not the bug in Perl that we thought it was.
I am saying this is an undetectable error in the book's code, that clearly the authors would have fixed had it thrown a warning or $?
other than 0
. It is a false positive, impossible to detect in this specific case.
It's easy to create "undetectable" errors if you don't enable strict
(without strict
, perl basically runs in perl 4 compatibility mode) or warnings
/-w
(which is for compatibility with perl 1.0!). For example, this program that tries to count lines with "word" in them:
$ printf 'a\nword\nb\nword\n' | perl -nle 'BEGIN { $count = 0; } $conut++ if /word/; END { print "$count occurrences found" if $count; }'
$
No output; exit status is 0.
I still think the lines from the book are misleading to the point of being erroneous, but this -e behavior is not the bug in Perl that we thought it was.
Yeah not a bug, seems to be like a special edge case that a normal person might make and be mystified about. Doesn't Perl have "looks like you meant to, blah blah blah" errors in other places? That's what I am thinking would be a good warning.
It's easy to create "undetectable" errors.
Yeah but your example is a mess that nobody would mistake for a file name. The one here looks like a file name and has been reproduced in print, probably thousands of times. If those authors can make that mistake and also not be able to detect it, then maybe it's more commonly made than you think. I bet thousands of genius Perl programmers and n00bies a like, have looked at that and though it was just running a file. Anyway. Good night.
It is unfortunate, but the documentation is very clear.
On Wed, Mar 27, 2024 at 11:21:54PM -0700, OODLER wrote:
Doesn't Perl have "looks like you blah blah blah" errors in other places? That's what I am thinking would be a good warning.
Yes, perl does. And if you enable warnings and strict, it will will display those warnings or errors. In this particular case, what you seem to be asking for is:
a special new warning or error which is enabled even in the absence of 'use strict' or use warnings', that:
in some as yet unspecified fashion, examines the code string argument, and if in some vague way that code string could also plausibly be a filename, prints an error rather than compiling and executing as normal;
and which produces almost no false positives; after all, people would be annoyed if their existing scripts suddenly broke.
I really can't see how you could avoid false positives. Is 'foo' possibly a filename? Looks like one to me. So should this be an error? perl -MFoo -e foo
Or maybe you want something narrow, like /^\w+.pl$/i ?
-- Dave's first rule of Opera: If something needs saying, say it: don't warble it.
An unfortunate misprint in that book, that's their problem to errata not ours.
This is just an error in the book. If you turn on warnings you get the hint:
$ perl -we FILE.pl
Unquoted string "pl" may clash with future reserved word at -e line 1.
Useless use of a constant ("FILEpl") in void context at -e line 1.
$ echo $?
0
Perl will treat bare words that don't have a definition as a string. It then concatenates those strings and warns about the void context.
Add strict and you get your error:
$ perl -Mstrict -we FILE.pl
Bareword "FILE" not allowed while "strict subs" in use at -e line 1.
Bareword "pl" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.
$ echo $?
255
Our mistake is not so much about this being a weird situation, but simply managing to intersperse code with text. As you are writing you have a bag of ideas and you move things around. Sometimes the code in the text is changed but not reverified. I don't know how this particular error got in there. We had a Google sheet that had a list of all the reported errata, but that has disappeared.
I know where some confusion may be.
Please not that in the current perldocs we see the e|E option defined like this:
[ [-e|-E] 'command' ] [ -- ] [ programfile ] [ argument ]...
The "--" is of course the differentiating factor. However, by the documents themselves this is a valid ending to any switch, not just -e. I think a modification of that line in perldoc would remove confusion, and yes the book is in error.
Thank you @briandfoy and everyone. I get -e
and -E
is maximally permissive, I've made a note in my book that this was a small error in regard to what those flags accept (and why it works without -w
).
@haxmeister - that is confusing, but not the original part of my consideration here. Had I read that I'd been even more confused! 😄
Description
It was discovered while going through Effective Perl Programming book (page 13), the following examples fail (or succeeds?) silently and with an exit status (
$?
) of0
(success):and
This only happens if there is no file path separator.
Steps to Reproduce
cd
to a directory with any Perl script (e.g.,foo.pl
)perl -e foo.pl
perl -E foo.pl
$?
is set to0
:echo $?
Expected behavior
We found this during a group Perl study session. We all expected that there to be an error, warning, or
$?
set as non-0
since this was an existing file.Perl configuration
Note, this might be a very old bug. It is even present in the Effective Perl Programming book, 2nd Edition (page 13):
CC'ing some present if they wish to correct or amend the report: @Util, @haxmeister