Ich versuche, diese Zeile aus einem Shell-Skript zu verstehen. Ich weiß, dass das $(..)
bedeutet, dass Sie das ausführen ..
und seine Ausgabe dort einfügen, wo Sie $()
in einer Anweisung suchen. Aber was passiert zwischen diesen Klammern? Was macht das \ls
und wie verhält sich das zu dem \
in den vorherigen Zeilen? Ist das eine \\
Aufteilung auf zwei Zeilen? Ist \ls
das dasselbe wie das normale ls
?
APPCLASSPATH=$CLASSPATH:$({ \
\ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \
\ls -1 "$VOLTDB_LIB"/*.jar; \
\ls -1 "$VOLTDB_LIB"/extension/*.jar; \
} 2> /dev/null | paste -sd ':' - )
Antwort1
Die Ausgabe der drei ls
Befehle wird an den Befehl weitergeleitet paste
, der sie zum folgenden Wert zusammenführt:
$VOLTDB_VOLTDB"/voltdb-*.jar:$VOLTDB_LIB"/*.jar:$VOLTDB_LIB"/extension/*.jar
NOTIZ:Die Variablen $VOLTDB_VOLTDB
und $VOLTDB_LIB
werden erweitert und es kann mehr Werte als nur eine Datei für jeden dieser ls
Befehle geben. Sehen Sie das *
dort? Das ist ein Glob-Zeichen, das als Platzhalter fungiert und beispielsweise auf alles zwischen der linken Seite (voltdb-) und der rechten Seite (.jar) erweitert wird.
Diese würden passen:
voltdb-1.jar
voltdb-blah.jar
voltdb-12345.jar
Alles wird dann in die Variable aufgenommen APPCLASSPATH
:
APPCLASSPATH=$CLASSPATH:$VOLTDB_VOLTDB"/voltdb....etc.
Der Befehl „Einfügen“
Hier ist ein Beispiel, in dem ich den Befehl verwende, seq
um eine Zahlenfolge von 1-10 zu generieren.
$ seq 10 | paste -sd ':' -
1:2:3:4:5:6:7:8:9:10
Sie können sehen, dass der paste
Befehl die Ausgabe zusammenführt und mit einem Doppelpunkt ( :
) trennt.
Sie können den Beispielbefehl auch folgendermaßen nachahmen:
$ { echo "hi1"; echo "hi2"; echo "hi3"; } | paste -sd ':' -
hi1:hi2:hi3
NOTIZ:Der -
Befehl „to the paste“ weist ihn an, die Eingabe von STDIN zu übernehmen und jedes Argument so auszudrucken, wie es eingeht, getrennt durch ein :
.
Mit verschiedenen Schaltern paste
lässt sich zudem eine Aufteilung der Daten in Gruppen erreichen, basierend auf der Anzahl der -
dahinter stehenden 's.
Beispiele einfügen
Hier ist ein Beispiel mit 2 -
.
$ seq 10 | paste - -
1 2
3 4
5 6
7 8
9 10
Hier sind 3 -
.
$ seq 10 | paste - - -
1 2 3
4 5 6
7 8 9
10
Es gibt also an, paste
wie viele Argumente paste
in jeder Zeile gedruckt werden sollen. Aber lassen Sie sich nicht verwirren, das Beispiel, mit dem Sie arbeiten, nimmt einfach die Eingabe von STDIN, trennt jedes Argument durch Leerzeichen und druckt es, gefolgt von einem :
. Wenn Sie mehrere -
's angeben, geben Sie an, paste
dass Argumente übernommen werden sollen, 2 auf einmal, 3 auf einmal usw.
Immer zwei Argumente gleichzeitig, getrennt durch :
's:
$ seq 10 | paste -d ':' - -
1:2
3:4
5:6
7:8
9:10
$ seq 10 | paste -d ':' - - -
1:2:3
4:5:6
7:8:9
10::
Wenn Sie übrigens den -s
Schalter einschließen, weisen Sie ihn an, paste
die Argumente seriell (nacheinander) zu übernehmen. Beobachten Sie, was passiert, wenn Sie ihn in einem der obigen Beispiele verwenden.
2 auf einmal:
$ seq 10 | paste -sd ':' - -
1:2:3:4:5:6:7:8:9:10
3 auf einmal:
$ seq 10 | paste -sd ':' - - -
1:2:3:4:5:6:7:8:9:10
Antwort2
$(command)
führt einen Befehl aus und ersetzt seine Ausgabe.
{ list; }
ist ein Gruppenbefehl, der mehrere Befehle in der aktuellen Shell-Umgebung ausführt. Er ist ähnlich wie (list)
, erstellt aber keine Subshell.
\command
wird verwendet, um Aliase zu Befehlen zu ignorieren, die das erwartete Verhalten eines Befehls erheblich verändern können.
Das \
am Ende der Zeile bedeutet lediglich, dass diese Zeile fortgesetzt wird, sodass die Shell die nächste Zeile als Teil der aktuellen betrachtet. Normalerweise nicht erforderlich, wenn dies aus dem Kontext (öffnende Klammer oder Anführungszeichen) offensichtlich ist.
Antwort3
APPCLASSPATH=$CLASSPATH:$({ \ \ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \ \ls -1 "$VOLTDB_LIB"/*.jar; \ \ls -1 "$VOLTDB_LIB"/extension/*.jar; \ } 2> /dev/null | paste -sd ':' - )
\ls
ist wie ls
, außer dass ls
der Backslash die Aliaserweiterung verhindert, wenn es sich um einen Alias handelt. Dies garantiert, dass der ls
Befehl verwendet wird und nicht irgendein Alias, der möglicherweise unerwünschte Ausgaben wie ein Klassifizierersuffix ( -F
) hinzufügt.
Die ls
Befehle, die mit vorhandenen Dateinamen als Argumente aufgerufen werden, listen ihre Argumente auf, eines pro Zeile. Die Option -1
hat keine Wirkung, da die Ausgabe von ls
an eine Pipe und nicht an ein Terminal geht. Wenn ls
ein Argument empfangen wird, das nicht der Name einer vorhandenen Datei ist, wird in der Standardausgabe nichts angezeigt, sondern stattdessen ein Fehler. Fehler von den ls
Befehlen werden von nirgendwohin umgeleitet 2> /dev/null
. Es gibt zwei Gründe, warum ls
möglicherweise ein Argument empfangen wird, das keine Datei ist: wenn eine der Variablen nicht auf ein vorhandenes, lesbares Verzeichnis verweist oder wenn keine Datei vorhanden ist, die dem Platzhaltermuster entspricht. In beiden Fällen wird das Muster unerweitert an übergeben ls
.
Die Backslashes am Ende der Zeilen bewirken, dass die Shell den folgenden Zeilenumbruch ignoriert. Keiner von ihnen ist hier sinnvoll, da die Shell an jeder Stelle, an der sie verwendet werden, einen optionalen Zeilenumbruch erwartet.
Die Klammern { … } gruppieren die Befehle. Der zusammengesetzte Befehl { \ls …; \ls …; \ls … ; }
wird weitergeleitet paste
und seine Fehler werden an umgeleitet /dev/null
.
Der paste
Befehl verbindet alle Eingabezeilen mit einem :
dazwischen. Dies ist äquivalent zu , außer dass am Ende tr '\n' :
kein ein eingefügt wird .:
Durch die Befehlsersetzung $(…)
wird die Ausgabe von paste
in interpoliert APPCLASSPATH
, wobei nach dem Wert der CLASSPATH
Variablen ein Doppelpunkt die beiden Teile trennt.
Hier ist eine vereinfachte Version. Diese unterscheidet sich geringfügig vom Original, da, wenn keines der Platzhaltermuster mit etwas übereinstimmt, „ gleich “ ohne zusätzlichen abschließenden Doppelpunkt APPCLASSPATH
ist (was wahrscheinlich wünschenswert ist).CLASSPATH
APPCLASSPATH=$CLASSPATH:$(
\ls "$VOLTDB_VOLTDB"/voltdb-*.jar "$VOLTDB_LIB"/*.jar "$VOLTDB_LIB"/extension/*.jar |
tr '\n' :) 2>/dev/null
APPCLASSPATH=${APPCLASSPATH%:}