Wie der Iteration über Argumente in einem Bash-Skript
Ich habe einen komplexeren Befehl, dass ich gerne ein shell - /bash-script. Ich kann schreiben, es in Bezug auf $1
einfach:
foo $1 args -o $1.ext
Möchte ich weitergeben kann mehrere input-Namen für das Skript. Was ist der richtige Weg, es zu tun?
Und, natürlich, will ich handle, Dateinamen mit Leerzeichen in Ihnen.
InformationsquelleAutor der Frage Thelema | 2008-11-01
Du musst angemeldet sein, um einen Kommentar abzugeben.
Verwenden
"$@"
zur Darstellung aller Argumente:Diese iteriert über jedes argument und drucken Sie es aus auf einer separaten Zeile. $@ verhält sich wie $*, außer, dass, wenn zitiert, die Argumente sind aufgebrochen richtig, wenn es Räume in Ihnen:
InformationsquelleAutor der Antwort Robert Gamble
Umschreiben des jetzt-gelöscht Antwort von VonC.
Robert Gamble lapidare Antwort befasst sich direkt mit der Frage.
Das man verstärkt auf einige Probleme mit Dateinamen, die Leerzeichen enthalten.
Siehe auch: ${1:+"$@"} in /bin/sh
Grundlegende these:
"$@"
korrekt ist, und$*
(ohne Anführungszeichen) ist fast immer falsch.Dies ist, weil
"$@"
funktioniert gut, wenn Argumente Leerzeichen enthalten, undfunktioniert genauso wie
$*
wenn Sie nicht.In einigen Fällen
"$*"
ist auch OK, aber"$@"
in der Regel (aber nichtimmer) funktioniert an den gleichen stellen.
Unquoted,
$@
und$*
äquivalent sind (und fast immer falsch).Also, was ist der Unterschied zwischen
$*
$@
"$*"
und"$@"
? Sie sind alle mit 'allen Argumenten für die shell', aber Sie machen unterschiedliche Dinge. Bei nicht börsennotierten,$*
und$@
tun die gleiche Sache. Sie behandeln jedes 'Wort' (Folge von nicht-whitespace-Zeichen) als separates argument. Die zitierten Formen sind sehr unterschiedlich, aber:"$*"
behandelt die argument-Liste als einen einzigen durch Leerschritte unterteilten Zeichenkette, in der Erwägung, dass"$@"
behandelt die Argumente, die fast genau so, wie Sie waren, als die in der Befehlszeile angegeben."$@"
erweitert, um gar nichts, wenn es keine positions-Argumente;"$*"
zu einer leeren Zeichenkette erweitert — und ja, es ist ein Unterschied, aber es kann schwer sein, um Sie wahrzunehmen.Weitere Informationen finden Sie unten, nach der Einführung des (nicht-standard) - Befehl
al
.Sekundären these: wenn Sie brauchen, um Prozess Argumente mit Leerzeichen und dann
geben Sie Sie an andere Befehle, dann müssen Sie manchmal nicht-standard -
tools zu unterstützen. (Oder Sie sollten die Verwendung von arrays gezielt:
"${array[@]}"
verhält sich Analog zu"$@"
.)Beispiel:
Warum nicht?
Es funktioniert nicht, weil die shell-Prozesse Zitate vor, es dehnt sich
Variablen.
So, um die Schale zu achten, die Zitate eingebettet in
$var
,verwenden Sie
eval
:Dieser wird wirklich schwierig, wenn du die Datei-Namen wie "
He said,
" (mit Anführungszeichen und doppelte Anführungszeichen und Leerzeichen)."Don't do this!"
Den Schalen (alle) machen es nicht besonders einfach zu handhaben wie
Sachen, so (komischerweise) viele Unix-Programme, die nicht tun, einen guten job
Umgang mit Ihnen.
Auf Unix -, eine mit dem Namen (einzelne Komponente) können beliebige Zeichen enthalten, mit Ausnahme
slash und NUL
'\0'
.Jedoch, die Schalen ermutigen, keine Leerzeichen oder newlines oder tabs
irgendwo in einem Pfad-Namen.
Es ist auch der Grund, warum die standard-Unix-Datei-Namen enthalten keine Leerzeichen, etc.
Beim Umgang mit Dateinamen, die Leerzeichen enthalten kann und andere
problematische Zeichen, müssen Sie sehr vorsichtig sein, und ich fand
lange her, dass ich brauchte ein Programm, dass ist nicht standard auf Unix.
Ich nenne es
escape
(version 1.1 datiert war 1989-08-23T16:01:45Z).Hier ist ein Beispiel von
escape
im Einsatz - mit der SCC-Steuerung.Es ist eine cover-Skript, die beide eine
delta
(denke check-in) und eineget
(denke check-out).Verschiedene Argumente, vor allem
-y
(der Grund, warum Sie die änderung vorgenommen haben)enthält Leerzeichen und Zeilenumbrüche.
Beachten Sie, dass das Skript stammt aus dem Jahr 1992, so benutzt es die back-ticks statt
$(cmd ...)
Schreibweise und verwenden keine#!/bin/sh
auf die erste Zeile.(Ich würde wahrscheinlich nicht verwenden, Flucht ganz so gründlich in diesen Tagen - es ist
nicht nötig, mit
-e
argument, zum Beispiel - aber insgesamt ist daseiner meiner einfacheren Skripte mit
escape
.)Den
escape
Programm einfach gibt seine Argumente aus, eher wieecho
das funktioniert, aber es sorgt dafür, dass die Argumente, die geschützt sind, für die Verwendung mit
eval
(eine Ebene voneval
; ich habe ein Programm, welches remote-shell habenAusführung, benötigt, um die Flucht der Ausgabe von
escape
).Habe ich ein weiteres Programm namens
al
, listet seine Argumente eine pro Zeile(und es ist noch mehr alte: version 1.1 datiert 1987-01-27T14:35:49).
Es ist sehr nützlich beim Debuggen von Skripts, wie es sein kann, an eine
Befehl-Linie, um zu sehen, was Argumente eigentlich sind die an den Befehl übergeben.
[Hinzugefügt:
Und nun zu zeigen, den Unterschied zwischen den verschiedenen
"$@"
Notationen, hier ist noch ein Beispiel:Feststellen, dass nichts bewahrt die ursprüngliche Leerzeichen zwischen den
*
und*/*
auf der Kommandozeile. Beachten Sie auch, dass Sie können ändern Sie die "command line arguments' in der shell mit:Dieser Sätze 4 Optionen, '
-new
', '-opt
', 'and
', und 'arg with space
'.]
Hmm, das ist ein ziemlich langer Antwort - vielleicht Exegese ist der bessere Begriff.
Quellcode für
escape
auf Anfrage erhältlich (E-Mail firstname dotNachname at gmail dot com).
Der source-code für
al
ist unglaublich einfach:Das ist alles. Es entspricht der
test.sh
Skript, dass Robert Gamble gezeigt und geschrieben werden kann, wie eine shell-Funktion (aber shell-Funktionen nicht vorhanden sind, in der lokale version der Bourne-shell, wenn ich zuerst schriebal
).Beachten Sie auch, dass Sie schreiben können
al
als ein einfaches shell-Skript:Die bedingte ist notwendig, so dass es erzeugt keine Ausgabe, wenn keine Argumente übergeben. Die
printf
Befehl erzeugen Sie eine leere Zeile mit der format-string argument, aber das C-Programm produziert nichts.InformationsquelleAutor der Antwort Jonathan Leffler
Beachten Sie, dass Robert ' s Antwort ist richtig, und es funktioniert in
sh
als gut. Sie können (portabel) vereinfachen es sogar noch weiter:ist äquivalent zu:
I. e., Sie brauchen nicht alles!
Prüfung (
$
ist die Eingabeaufforderung):I ersten Lesen über diese, in Unix-Programmierumgebung von Kernighan und Pike.
In
bash
help for
Dokumente:InformationsquelleAutor der Antwort Alok Singhal
Für einfache Fälle können Sie auch
shift
.Es behandelt die argument-Liste wie eine Schlange, jeder
shift
wirft das erste argument aus,Anzahl der jedes argument, das übrig ist, wird dekrementiert.
InformationsquelleAutor der Antwort nuoritoveri
Können Sie auch auf Sie als array-Elemente, zum Beispiel wenn Sie nicht möchten, Durchlaufen Sie alle
InformationsquelleAutor der Antwort baz
InformationsquelleAutor der Antwort g24l