In the Perl documentation, perlrun(1) suggests launching Perl scripts using a bilingual shell/Perl header:
#!/bin/sh
#! -*-perl-*-
eval 'exec perl -x -wS $0 ${1+"$@"}'
if 0;
What does ${1+"$@"}
mean? I tried using "$@"
instead (using Bash as /bin/sh), and it seems to work just as well.
Edit
Two answers below say that it's supposed to be ${1:+"$@"}
. I am aware of the ${parameter:+word}
("Use Alternate Value") syntax documented in bash(1). However, I am unconvinced, because
-
Both
${1+"$@"}
and"$@"
work just fine, even when there are no parameters. If I create simple.sh as#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 "$@"' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
and question.sh as
#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 ${1+"$@"}' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
I can get both to work identically:
$ ./question.sh $VAR1 = []; $ ./question.sh a $VAR1 = [ 'a' ]; $ ./question.sh a 'b c' $VAR1 = [ 'a', 'b c' ]; $ ./question.sh "" $VAR1 = [ '' ]; $ ./simple.sh $VAR1 = []; $ ./simple.sh a $VAR1 = [ 'a' ]; $ ./simple.sh a 'b c' $VAR1 = [ 'a', 'b c' ]; $ ./simple.sh "" $VAR1 = [ '' ];
-
Other sources on the Internet also use
${1+"$@"}
, including one hacker who seems to know what he's doing.
Perhaps ${parameter+word}
is an undocumented alternate (or deprecated) syntax for ${parameter:+word}
? Could someone confirm that hypothesis?
Best Answer
That's for compatibility with the Bourne shell. The Bourne shell was an old shell that was first released with Unix version 7 in 1979 and was still common until the mid 90s as
/bin/sh
on most commercial Unices.It is the ancestor of most Bourne-like shells like
ksh
,bash
orzsh
.It had a few awkward features many of which have been fixed in
ksh
and the other shells and the new standard specification ofsh
, one of which is this:With the Bourne shell (at least those variants where it has not been fixed):
"$@"
expands to one empty argument if the list of positional parameters is empty ($# == 0
) instead of no argument at all.${var+something}
expands to "something" unless$var
is unset. It is clearly documented in all shells but hard to find in thebash
documentation as you need to pay attention to this sentence:So
${1+"$@"}
expands to"$@"
only if$1
is set ($# > 0
) which works around that limitation of the Bourne shell.Note that the Bourne shell is the only shell with that problem. Modern
sh
s (that issh
conforming to the POSIX specification ofsh
(which the Bourne shell is not)) don't have that issue. So you only need that if you need your code to work on very old systems where/bin/sh
might be a Bourne shell instead of a standard shell (note that POSIX doesn't specify the location of the standardsh
, so for instance on Solaris before Solaris 11,/bin/sh
was still a Bourne shell (though did not have that particular issue) while the normal/standardsh
was in another location (/usr/xpg4/bin/sh
)).There is a problem in that
perlrun
perldoc page in that$0
is not quoted though.See http://www.in-ulm.de/~mascheck/various/bourne_args/ for more information.