In der Perl-Dokumentation schlägt Perlrun (1) vor, Perl-Skripte mit einem zweisprachigen Shell- / Perl-Header zu starten:
#!/bin/sh
#! -*-perl-*-
eval 'exec perl -x -wS $0 ${1+"$@"}'
if 0;
Was heißt ${1+"$@"}
das? Ich habe versucht, "$@"
stattdessen (mit Bash als / bin / sh), und es scheint genauso gut zu funktionieren.
Bearbeiten
Zwei Antworten unten sagen, dass es sein soll ${1:+"$@"}
. Mir ist die ${parameter:+word}
in bash (1) dokumentierte Syntax ("Use Alternate Value") bekannt. Ich bin jedoch nicht überzeugt, weil
Beides
${1+"$@"}
und"$@"
funktionieren einwandfrei, auch wenn keine Parameter vorhanden sind. Wenn ich simple.sh als erstelle#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 "$@"' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
und question.sh als
#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 ${1+"$@"}' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
Ich kann beide dazu bringen, identisch zu arbeiten:
$ ./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 = [ '' ];
Andere Quellen im Internet verwenden ebenfalls
${1+"$@"}
, darunter ein Hacker, der zu wissen scheint, was er tut.
Vielleicht ${parameter+word}
ist eine undokumentierte alternative (oder veraltete) Syntax für ${parameter:+word}
? Könnte jemand diese Hypothese bestätigen?
Antworten:
Dies dient der Kompatibilität mit der Bourne-Shell. Die Bourne-Shell war eine alte Shell, die 1979 zum ersten Mal mit Unix Version 7 veröffentlicht wurde und bis Mitte der 90er Jahre wie
/bin/sh
bei den meisten kommerziellen Unices üblich war.Es ist der Vorfahr der meisten Bourne-ähnlichen Muscheln wie
ksh
,bash
oderzsh
.Es hatte einige unangenehme Eigenschaften, von denen viele in
ksh
und die anderen Schalen und die neue Standardspezifikation von repariert worden sindsh
, von denen eine dieses ist:Mit der Bourne-Shell (zumindest in den Varianten, in denen dies nicht behoben wurde):
"$@"
Wird zu einem leeren Argument erweitert, wenn die Liste der Positionsparameter leer ist ($# == 0
), anstatt überhaupt kein Argument.${var+something}
Erweitert sich zu "etwas", es$var
sei denn, es ist nicht festgelegt. Es ist in allen Shells klar dokumentiert, aber in derbash
Dokumentation schwer zu finden, da Sie auf diesen Satz achten müssen:So
${1+"$@"}
dehnt sich auf"$@"
nur , wenn$1
gesetzt ($# > 0
) , die arbeitet rund um die Begrenzung der Bourne - Shell.Beachten Sie, dass die Bourne-Shell die einzige Shell mit diesem Problem ist. Moderne
sh
s (diesh
der POSIX-Spezifikation entsprechensh
(was die Bourne-Shell nicht tut)) haben dieses Problem nicht. Sie benötigen dies also nur, wenn Sie Ihren Code für sehr alte Systeme benötigen, auf denen/bin/sh
möglicherweise eine Bourne-Shell anstelle einer Standard-Shell verwendet wird (beachten Sie, dass POSIX den Speicherort des Standards nicht angibtsh
, z. B. unter Solaris vor Solaris 11./bin/sh
war immer noch eine Bourne-Shell (obwohl es dieses spezielle Problem nicht gab), während sich das normale / standardsh
an einem anderen Ort befand (/usr/xpg4/bin/sh
)).Es gibt ein Problem in dieser
perlrun
Perldoc-Seite, das$0
jedoch nicht in Anführungszeichen gesetzt ist.Weitere Informationen finden Sie unter http://www.in-ulm.de/~mascheck/various/bourne_args/ .
quelle
Es gibt einen Unterschied zwischen:
und
In einem übergeben Sie ein Argument, das eine leere Zeichenfolge ist. Im zweiten Fall werden keine Argumente übergeben.
Für beide „$ @“ wird auf die gleiche Sache zu:
""
. Aber der Einsatz${1:+"$@"}
wäre""
für die erste und keine Argumente für die zweite übergeben, die die Absicht war.Dies ist wichtig, wenn Sie das folgende Skript namens sshwrapper ausführen, das Sie mit einem optionalen Befehl oder ohne Argumente aufrufen, um eine interaktive Shell abzurufen.
Dies würde versuchen, "" auf dem entfernten Host (der gerade zurückkehrt) zu "" laufen, es wäre keine interaktive Shell.
Startet eine interaktive Shell auf dem Remote-Host, da die ausführbare Datei die Variable nicht als leere Zeichenfolge interpretiert.
Lesen Sie die Verwendung von "$ {parameter: + word}" ("Use Alternate Value") und ähnlichen variablen Erweiterungszeichenfolgen in den bash-Handbuchseiten.
quelle
sh
Implementierung zu gelten (siehe andere Antwort).${1:+"$@"}
würde zu keinem Argument führen, wenn$1
leer wäre. Sie möchten${1+"$@"}
. Grundsätzlich haben Sie es umgekehrt.Ich habe die Antwort von Stéphane Chazelas zusammengefasst:
Wenn also die zweite mit dem Parameter "" verwendet wird, bedeutet dies, dass $ 1 null ist, aber es wird nicht geprüft, ob es null ist oder nicht. Es wird nur angezeigt, dass es bereits festgelegt wurde. Wenn Sie jedoch $ {1: + "$ @"} 'mit "" verwenden, wird es nicht
$@
mehr erweitert.quelle