In der Regel wird $0
in einem Skript der Name des Skripts oder der Name des aufgerufenen Skripts (einschließlich des Pfads) festgelegt. Wenn ich jedoch bash
mit der -c
Option verwende, $0
wird auf das erste der nach der Befehlszeichenfolge übergebenen Argumente gesetzt:
bash -c 'echo $0 ' foo bar
# foo
In der Tat scheint es, dass Positionsparameter verschoben wurden, aber einschließlich $0
. Jedoch shift
in der Befehlsfolge wirkt sich nicht aus $0
(wie normal):
bash -c 'echo $0; shift; echo $0 ' foo bar
# foo
# foo
Warum dieses anscheinend merkwürdige Verhalten für Befehlszeichenfolgen? Beachten Sie, dass ich nach dem Grund und der Begründung für die Implementierung eines solchen merkwürdigen Verhaltens suche.
Man könnte spekulieren, dass ein solcher Befehlsstring den $0
normalerweise definierten Parameter nicht benötigt , so dass er aus Sparsamkeitsgründen auch für normale Argumente verwendet wird. In diesem Fall ist das Verhalten von shift
jedoch ungerade. Eine andere Möglichkeit besteht $0
darin, das Verhalten von Programmen zu definieren (a la bash
aufgerufen als sh
oder vim
aufgerufen als vi
), aber das kann nicht sein, da dies $0
nur in der Befehlszeichenfolge und nicht von Programmen gesehen wird, die in dieser aufgerufen werden. Ich kann mir keinen anderen Verwendungszweck vorstellen $0
, daher bin ich ratlos, dies zu erklären.
-
für das$0
Argument als eine Redewendung gesehen, wie insh -c 'foo $1 $2' - a b
. Auf diese Weise sieht es ziemlich normal aus (wenn Sie herausgefunden haben, was das-
bedeutet)echo 'echo the other side of this pipe globs "$@"' | sh -s -- *
aber leider auch$0
generell keinen einstellbaren Parameter mit der-s
Option tream angeben ... Sie kann jedoch auf viele der gleichen Arten verwendet werden, wie diesxargs
generell der Fall ist. Und noch andere.--
, das hätte die übliche Interpretation von "Ab hier fängt die Argumente an" haben können, die man in einigen anderen Programmen sieht. Andererseits könnte das diejenigen verwirren, die nicht mit-c
dem Gedanken vertraut sind , dass--
tatsächlich diese Interpretation vorliegt.Antworten:
Dies gibt Ihnen die Möglichkeit,
$0
bei Verwendung eines Inline-Skripts festzulegen / auszuwählen . Sonst$0
wäre es einfachbash
.Dann können Sie zum Beispiel tun:
Das taten nicht alle Muscheln. Die Bourne-Shell hat es getan. In der Korn- (und Almquist-) Shell wurde stattdessen der erste Parameter ausgewählt
$1
. POSIX entschied sich schließlich für den Bourne-Weg,ksh
undash
Derivate kehrten später darauf zurück (mehr dazu unter http://www.in-ulm.de/~mascheck/various/find/#shell ). Das ist für eine lange Zeit für die bedeutete , dasssh
(die auf dem System abhängig wurde auf der Grundlage der Bourne, Almquist oder Korn - Shell), Sie nicht wissen , ob das erste Argument ging in$0
oder$1
so für die Portabilität, mußte man Dinge wie:Oder:
Zum Glück hat POSIX das neue Verhalten angegeben, in das das erste Argument eingeht
$0
, sodass wir es jetzt portabel machen können:quelle
bash -c 'echo txt files are "$@"' meaningful-arg0-for-error *.txt
auf Ubuntu 14.04, bashversion 4.3.11(1)-release
, und ich habe:txt files are *.txt
. Ootxt
Dateien im aktuellen Verzeichnis). Siehe auchbash -c 'echo "${1?}"' foo
sh -c 'shift "$2"; echo txt files are "$@"' tentative-arg0 3 2 *.txt
ist fantastisch erfinderisch!SHELL -c 'shift $1; command' 2 1 arg1 arg2 ...
haha ...Dieses Verhalten wird von POSIX definiert :
Warum möchten Sie dieses Verhalten: Dies gleicht die Lücke zwischen einem Skript und einer
-c
Zeichenfolge aus. Sie können direkt zwischen den beiden ohne Änderung des Verhaltens konvertieren. Andere Bereiche stützen sich darauf, dass diese identisch sind.Dies
exec
hängt auch damit zusammen$0
, wie Programmargumente im Allgemeinen funktionieren: Letztendlich wird eine der Funktionen aufgerufen, in denen sich auch das erste bereitgestellte Argument befindet , und ebenso häufig ist dieses Argument dasselbe wie das ausführbare Programm, das Sie ausführen. Manchmal möchten Sie jedoch einen besonderen Wert, und es gibt einfach keinen anderen Weg, ihn zu erhalten. Vorausgesetzt, dass das Argument existiert, muss es auf etwas abgebildet werden, und der Benutzer muss in der Lage sein, festzulegen, was das ist.Diese Konsistenz (und der wahrscheinliche historische Unfall) führen zu der Situation, die Sie finden.
quelle
argv[0]
.$0
wird nur auf den übergebenenargv[0]
Wert gesetzt,execve()
wenn es wiesh
oder istbash
. Wird für Skripte$0
auf den Pfad gesetzt, der als Argument 1, 2 ... für den Interpreter angegeben ist (und für Skripte, die direkt ausgeführt werden, der vom ersten Pfadargument stammt, um () auszuführen).