Wie erweiterten Pfadexpansionsmuster in zitierte Ausdrücke zu entkommen?
-
22-08-2019 - |
Frage
Zusätzlich zu den grundlegenden *
, ?
und [...]
Muster stellt die Schlag-Shell verlängerte Muster Operatoren wie !(pattern-list)
Matching ( „mit einer Ausnahme der gegebenen Muster alle Ergebnisse“). Die extglob
Shell Option muss eingestellt werden, um sie zu verwenden. Ein Beispiel:
~$ mkdir test ; cd test ; touch file1 file2 file3
~/test$ echo *
file1 file2 file3
~/test$ shopt -s extglob # make sure extglob is set
~/test$ echo !(file2)
file1 file3
Wenn ich eine Shell-Expression zu einem Programm übergeben, die es in einer Unterschale ausgeführt wird, bewirkt, dass der Bediener einen Fehler. Hier ist ein Test, der läuft eine Unterschale direkt (hier habe ich aus einem anderen Verzeichnis bin Ausführung sicher Expansion machen geschieht nicht vorzeitig):
~/test$ cd ..
~$ bash -c "cd test ; echo *"
file1 file2 file3
~$ bash -c "cd test ; echo !(file2)" # expected output: file1 file3
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `cd test ; echo !(file2)'
Ich habe alle Arten von entkommen versucht, aber nichts, was ich mit richtig gearbeitet habe kommen hat. Ich habe auch im Verdacht extglob
ist nicht in einer Unterschale gesetzt, aber das ist nicht der Fall:
~$ bash -c "shopt -s extglob ; cd test ; echo !(file2)"
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `cd test ; echo !(file2)'
Jede Lösung geschätzt!
Lösung
$ bash -O extglob -c 'echo !(file2)' file1 file3
Andere Tipps
bash analysiert jede Zeile, bevor sie ausgeführt wird, so „shopt es extglob“ nicht wirksam sind, wenn bash die Globbing Muster-Syntax zu validieren. Die Option kann nicht auf der gleichen Linie aktiviert werden. Deshalb ist die "bash -O extglob -c 'xyz'" Lösung (von Randy Proctor) arbeitet und erforderlich ist.
Hier ist eine andere Art und Weise, wenn Sie eval
vermeiden wollen, und Sie müssen drehen können extglob ein und aus in der Subshell. setzen Sie Ihre Muster nur in einer Variablen:
bash -c 'shopt -s extglob; cd test; patt="!(file2)"; echo $patt; shopt -u extglob; echo $patt'
gibt die folgende Ausgabe:
file1 file3
!(file2)
Demonstrieren, dass extglob wurde geschärft und entschärft. Wenn die erste echo
Anführungszeichen um den $patt
hätte, wäre es nur das Muster wie die zweite echo
ausspucken (was wahrscheinlich sollte zitiert haben).
Nun, ich habe keine wirkliche experince mit extglob , aber ich kann es durch Wickeln des echo
in einem eval
zu arbeiten:
$ bash -c 'shopt -s extglob ; cd test ; eval "echo !(file2)"'
file1 file3