Wie der Kommentar von Goldlöckchen und die Referenzen der Menschheit beschreiben, werden
shift
die Positionsparameter ( $1
, $2
usw.) neu zugewiesen , sodass $1
der alte Wert von $2
,
$2
der Wert von $3
usw. übernommen wird. *
Der alte Wert von $1
wird verworfen. ( $0
wird nicht geändert.) Einige Gründe dafür sind:
- Hiermit können Sie leichter auf das zehnte Argument zugreifen (sofern es eines gibt).
$10
funktioniert nicht - es wird als $1
verkettet mit einem interpretiert 0
(und könnte so etwas produzieren Hello0
). Nach a shift
wird das zehnte Argument $9
. (In den meisten modernen Shells können Sie jedoch verwenden ${10}
.)
- Wie der Bash-Leitfaden für Anfänger zeigt, kann er zum Durchlaufen der Argumente verwendet werden. IMNSHO, das ist ungeschickt;
for
ist viel besser dafür.
- Wie in Ihrem Beispielskript können Sie alle Argumente mit Ausnahme einiger weniger auf die gleiche Weise verarbeiten. Beispiel: In Ihrem Skript sind
$1
und $2
Textzeichenfolgen, während $3
und alle anderen Parameter Dateinamen sind.
So spielt es sich ab. Angenommen, Ihr Skript wird aufgerufen Patryk_script
und heißt
Patryk_script USSR Russia Treaty1 Atlas2 Pravda3
Das Skript sieht
$1 = USSR
$2 = Russia
$3 = Treaty1
$4 = Atlas2
$5 = Pravda3
Die Anweisung ostr="$1"
setzt die Variable ostr
auf USSR
. Die erste shift
Anweisung ändert die Positionsparameter wie folgt:
$1 = Russia
$2 = Treaty1
$3 = Atlas2
$4 = Pravda3
Die Anweisung nstr="$1"
setzt die Variable nstr
auf Russia
. Die zweite shift
Anweisung ändert die Positionsparameter wie folgt:
$1 = Treaty1
$2 = Atlas2
$3 = Pravda3
Und dann die for
Schleife Änderungen USSR
( $ostr
) zu Russia
( $nstr
) in den Akten Treaty1
, Atlas2
und Pravda3
.
Es gibt einige Probleme mit dem Skript.
für Datei in $ @; machen
Wenn das Skript als aufgerufen wird
Patryk_script UdSSR Russland Vertrag1 "Weltatlas2" Pravda3
es sieht
$ 1 = UdSSR
$ 2 = Russland
$ 3 = Vertrag1
$ 4 = Weltatlas2
$ 5 = Pravda3
aber, weil $@
nicht zitiert wird, in dem Raum World Atlas2
ist nicht in Anführungszeichen gesetzt, und die for
Schleife denkt , dass es vier Dateien hat: Treaty1
, World
, Atlas2
, und Pravda3
. Dies sollte auch so sein
für Datei in "$ @"; machen
(um Sonderzeichen in den Argumenten zu zitieren) oder einfach
für Datei zu tun
(was der längeren Version entspricht).
eval "sed 's /" $ ostr "/" $ nstr "/ g' $ file"
Dies ist nicht unbedingt erforderlich eval
, und die Weitergabe ungeprüfter Benutzereingaben an eval
kann gefährlich sein. Zum Beispiel, wenn das Skript als aufgerufen wird
Patryk_script "'; rm *;'" Russland-Vertrag1 Atlas2 Pravda3
es wird ausgeführt rm *
! Dies ist ein großes Problem, wenn das Skript mit höheren Berechtigungen ausgeführt werden kann als die des Benutzers, der es aufruft. Zum Beispiel, wenn es über sudo
eine Weboberfläche ausgeführt oder von dieser aufgerufen werden kann. Es ist wahrscheinlich nicht so wichtig, wenn Sie es nur als Sie selbst in Ihrem Verzeichnis verwenden. Aber es kann geändert werden
sed "s / $ ostr / $ nstr / g" "$ file"
Dies birgt immer noch einige Risiken, die jedoch viel weniger schwerwiegend sind.
if [ -f $file ]
, > $file.tmp
Und mv $file.tmp $file
sollte es sein if [ -f "$file" ]
, > "$file.tmp"
und mv "$file.tmp" "$file"
jeweils mit Dateinamen umgehen , die Leerzeichen (oder andere lustige Zeichen) in ihnen haben könnte. (Mit dem eval "sed …
Befehl werden auch Dateinamen mit Leerzeichen entstellt.)
* shift
akzeptiert ein optionales Argument: eine positive Ganzzahl, die angibt, wie viele Parameter verschoben werden sollen. Der Standardwert ist eins ( 1
). Zum Beispiel shift 4
verursacht $5
zu werden $1
,
$6
zu werden $2
und so weiter. (Beachten Sie, dass das Beispiel im Bash-Handbuch für Anfänger falsch ist.) Daher kann Ihr Skript geändert werden
ostr="$1"
nstr="$2"
shift 2
was als klarer angesehen werden könnte.
Endnote / Warnung:
Die Windows-Eingabeaufforderungssprache (Batch-Datei) unterstützt auch einen SHIFT
Befehl, der im Grunde das Gleiche wie der shift
Befehl in Unix-Shells tut , mit einem auffälligen Unterschied, den ich verstecke, um zu verhindern, dass die Benutzer dadurch verwirrt werden:
- Ein Befehl wie
SHIFT 4
ist ein Fehler, der die Fehlermeldung "Ungültiger Parameter für SHIFT-Befehl" ausgibt.
SHIFT /n
, wobei n
eine ganze Zahl zwischen 0 und 8 ist, ist gültig - aber es werden keine Zeiten verschoben . Es verschiebt sich einmal, beginnend mit dem n- ten Argument. Dies bewirkt, dass (das fünfte Argument) zu wird und so weiter, wobei die Argumente 0 bis 3 allein bleiben.n
SHIFT /4
%5
%4,
%6
%5
pushd
undpopd
).