Bash-Skript, das ein Programm mit einigen Sternchen in Argumenten aufruft
1216
kirelagin
Ich habe die letzte Stunde damit verbracht, ein ziemlich einfaches Bash-Skript zu schreiben, und ich war noch nie so dumm.
Ich habe also eine Liste von Strings (die Paketauswahlspezifikationen für einen Paketmanager sind, falls dies wichtig ist), die Sternchen enthalten können. Ich muss eine Befehlszeile erstellen, die diese Sternchen enthält, und dann ein Programm aufrufen. Hier ist mein naiver Versuch:
xs="foo/bar */*" xs_cmd="" for x in $xs; do xs_cmd="$xs_cmd -0 $x " done echo $xs_cmd
Ich brauche den echoAnruf als gleichwertig
echo -0 foo/bar -0 '*/*'
welche Ausgänge -0 foo/bar -0 */*.
PS In der Realität ist die erste Zeile etwas komplexer: xs="$some foo/bar */* $(get_others)".
Wenn Sie dieses Skript in einem Verzeichnis ausführen a/b, wird es -0 foo/bar -0 a/bstattdessen angezeigt.
Wenn ich die letzte Zeile umstelle
echo "$xs_cmd" # note the quotes
Ich erhalte -0 foo/bar -0 a/b und vor allem das ist nicht das, was ich will, da ich jetzt den Aufruf echomit einem einzigen Argumente, und darüber hinaus, das mir sagt, dass die Expansion früher geschieht, wahrscheinlich in der forSchleife.
Aber ich kann die forZeile nicht ändern, weil
for x in "$xs"; do # note the quotes
Die Schleife wird nur einmal iteriert: -0 foo/bar */*(es gibt eine einzige -0). Das Hinzufügen dieser Anführungszeichen ist daher keine Option.
Wenn ich jetzt zum ursprünglichen Skript zurückspringe und die erste Zeile mit ersetze
xs="foo/bar '*/*'" # note additional single quotes
Ich bekomme -0 foo/bar -0 '*/*'(einfache Anführungszeichen sollten nicht da sein).
Es scheint, dass ich jede Kombination von Anführungszeichen und Backslash-Escape von Sternchen ausprobiert habe, und ich habe buchstäblich keine Ahnung, was ich jetzt tun soll.
2 Antworten auf die Frage
0
AFH
Ich habe Ihr Original-Skript verwendet, jedoch mit einfachen Anführungszeichen in der ersten Zeile (nur), und es funktionierte, wie ich glaube, dass Sie es wollen ( -0vor jedem Dateipfad): -
xs='foo/bar */*' xs_cmd="" for x in $xs; do xs_cmd="$xs_cmd -0 $x " done echo $xs_cmd
Sie werden wahrscheinlich Probleme finden, wenn Sie sie verwenden, wenn in einem der Dateipfade Leerzeichen enthalten sind. Wenn ja, ändern Sie den Befehl in der Schleife in: -
xs_cmd="$xs_cmd -0 \"$x\" "
Nein, das führt immer noch eine Erweiterung in der `for`-Schleife durch und gibt` a / b` anstelle von `* / *` aus. Ein weiteres Problem ist, dass die erste Zeile in Wirklichkeit etwas komplexer ist. Ich werde die Frage in einer Minute aktualisieren.
kirelagin vor 10 Jahren
0
Ich dachte, Sie wollten es in der 'for'-Schleife erweitern. Ich habe es auf Ubuntu 14.04 getestet und habe -0 "foo / bar" -0 "dir / file" -0 "dir / file" ... "erhalten
AFH vor 10 Jahren
0
Vielleicht möchten Sie meine Frage noch einmal lesen, insbesondere den Teil vor dem horizontalen Lineal, der die gewünschte Ausgabe ergibt: _no_ Expansion sollte durchgeführt werden; Ich brauche alle Sternchen an Ort und Stelle.
kirelagin vor 10 Jahren
0
OK. Ich habe etwas gefunden, das funktioniert. Machen Sie Ihre erste Zeile `xs =" foo / bar @ / @ "`, und fügen Sie nach der `for'-Schleife die Zeile` xs_cmd = $ (echo $ xs_cmd | sed "s / @ / \ * / g") `hinzu. Wenn Sie kein Zeichen wie "@" finden, das sich in keinem Dateinamen befindet, verwenden Sie "xs =" foo / bar /// "" und "xs_cmd = $" (echo $ xs_cmd | sed) - /// - \ * / \ * - g ")`. Ich schlug vor, '@' zu verwenden, da es einfacher ist, andere Zeichenfolgen mit Sternchen zu verallgemeinern.
AFH vor 10 Jahren
0
Jetzt habe ich `xs_cmd`, was eine Zeichenfolge mit einigen Sternen ist. Wie gebe ich es an den Befehl (in meinem Beispiel "echo")? `echo $ xs_cmd` führt eine Erweiterung aus. `echo" $ xs_cmd "` ruft `echo 'mit einem einzigen Argument auf.
kirelagin vor 10 Jahren
0
Ich meine, Shell-Programmierung ist wirklich verrückt. Ich hätte dieses Programm in zwei Minuten in einer anderen Sprache schreiben und in nur einem Versuch zum Laufen bringen können. Aber jetzt möchte ich wirklich wissen, wie man dies in der Shell schreibt!
kirelagin vor 10 Jahren
0
Da Sie gegen die Dateinamenerweiterung kämpfen, sollten Sie sie in diesem Kontext mit set -f deaktivieren und anschließend mit set + f wiederherstellen.
AFH vor 10 Jahren
0
Ah natürlich! Nun, ich würde das als Problemumgehung einstufen, keine echte Lösung (weil ich immer noch daran interessiert bin, wie man das direkt macht), aber das funktioniert. Vielen Dank!
kirelagin vor 10 Jahren
0
Ich habe über Ihren Kommentar nachgedacht und komme nicht zu dem Schluss, dass es sich um eine Arbeitsrunde handelt. Ihr Skript schlägt fehl, weil Sternchen erweitert werden, wenn Sie nicht wollen, dass das Stoppen der Erweiterung zur falschen Zeit eine Lösung darstellt, da die anderen Vorschläge genau dies tun.
AFH vor 10 Jahren
0
0
oxij
Je nachdem, was Sie erreichen wollen, müssen Sie entweder Folgendes angeben */*:
xs="foo/bar '*/*'" #! xs_cmd="" for x in $xs ; do xs_cmd="$xs_cmd -0 $x " done echo $xs_cmd eval echo $xs_cmd eval "echo $xs_cmd"
oder verwenden Sie Arrays oder beides:
xs=("foo/bar" "*/*") #! xs_cmd="" for x in "$"; do xs_cmd="$xs_cmd -0 '$x' " #! done echo "$xs_cmd" eval "echo $xs_cmd"
Wie in meiner Frage erwähnt, führt Ihr erster Vorschlag zu folgender Ausgabe: `-0 foo / bar -0 '* / *'`, dh die Anführungszeichen werden buchstäblich an das Programm übergeben. Ihr zweiter Vorschlag führt zu "-0" foo / bar "-0" a / b "", wobei _both_ Anführungszeichen an das Programm ** übergibt und ** eine Erweiterung durchführt, während ich beides nicht brauche.
kirelagin vor 10 Jahren
0