Bash-Skript, das ein Programm mit einigen Sternchen in Argumenten aufruft

1176
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.

0

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 9 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 9 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 9 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 9 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 9 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 9 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 9 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 9 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 9 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 9 Jahren 0