Eine bessere Alternative.

Eine bessere Alternative.

Ich versuche, eine Zeichenfolge mit einem Platzhalter und einer Sammlung von Erweiterungen in Klammern zu erweitern. Nichts scheint zu funktionieren, wie das folgende Beispiel zeigt. Die Variable firstListwird problemlos erweitert, aber weder secondList, thirdListnoch fourthListwird richtig erweitert. Ich habe auch verschiedene Versionen von ausprobiert, evalaber keine funktioniert. Für jede Hilfe wäre ich dankbar.

#!/bin/bash
touch a.ext1
touch b.ext1
firstList='*.ext1'
ls  $firstList
touch a.ext2
touch b.ext2
secondList='*.{ext1,ext2}'
ls $secondList 
ls '$secondList'
ls "$secondList"
thirdList=*.{ext1,ext2}
ls $thirdList  
ls '$thirdList'
ls "$thirdList"
fourthList="*.{ext1,ext2}"
ls $fourthList
ls '$fourthList'
ls "$fourthList"

Antwort1

DerHülsewird nur erweitert *, wenn keine Anführungszeichen gesetzt sind. Jegliche Anführungszeichen verhindern die Erweiterung durch die Shell.

Außerdem muss eine Klammererweiterung frei von Anführungszeichen sein, damit sie von der Shell erweitert werden kann.

So funktioniert es (verwenden wir Echo, um zu sehen, was die Shell macht):

$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2

Auch wenn es Dateien mit anderen Namen gibt:

$ touch {a,b}.{ext1,ext2} {c,d}.{ext3,ext4} none
ls
a.ext1  a.ext2  b.ext1  b.ext2  c.ext3  c.ext4  d.ext3  d.ext4  none

$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2

Warum das funktioniert?

Es ist wichtig, dass wir verstehen, warum das funktioniert. Es liegt an der Reihenfolge der Erweiterung. Zuerst die „Klammernerweiterung“ und später (die letzte) die „Pfadnamenerweiterung“ (auch bekannt als Glob-Erweiterung).

Brace --> Parameter (variable) --> Pathname

Wir können die „Pfadnamenerweiterung“ für einen Moment ausschalten:

$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2

Die „Pfadnamenerweiterung“ erhält zwei Argumente: *.ext1und *.ext2.

$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2

Das Problem ist, dass wir keine Variable für die Klammererweiterung verwenden können.
Es wurde bereits viele Male erklärt fürVerwenden einer Variablen innerhalb einer „Klammernerweiterung“

Um eine „Klammernerweiterung“ zu erweitern, die das Ergebnis einer „Variablenerweiterung“ ist, müssen Sie die Befehlszeile mit erneut an die Shell übermitteln eval.

$ list={ext1,ext2}
$ eval echo '*.'"$list"

Klammer -->Variable--> Globus || -->Befestigen--> Variabel -->Glob
........ hier zitiert -->^^^^^^ || eval ^^^^^^^^^^^^^^^^^^^^^^^^^

Werte der Dateinamen bringen kein Ausführungsproblem für eval:

$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2

Der Wert von $listkönnte jedoch unsicher sein. Der Wert von $listwird jedoch vom Skriptautor festgelegt. Der Skriptautor hat die Kontrolle über eval: Verwenden Sie einfach keine extern festgelegten Werte für $list. Versuchen Sie Folgendes:

#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"

Eine bessere Alternative.

Eine Alternative (ohne eval) istBash „Erweiterte Muster“ verwenden:

#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list

Hinweis: Bitte beachten Sie, dass beide Lösungen (eval und patterns) (wie geschrieben) für Dateinamen mit Leerzeichen oder neuen Zeilen sicher sind. Sie schlagen jedoch für ein $listmit Leerzeichen fehl, weil $listes nicht in Anführungszeichen steht oder die eval die Anführungszeichen entfernt.

Antwort2

Halten:

secondList='*.{ext1,ext2}'
ls $secondList 

Das Problem ist, dassKlammererweiterungerledigtVor variable ErweiterungDas bedeutet, dass im obigen Beispiel nie eine Klammererweiterung durchgeführt wird.

Dies liegt daran, dass Bash beim ersten Betrachten der Befehlszeile keine Klammern sieht. Nachdem secondListsie erweitert wurde, ist es zu spät.

Folgendes funktioniert:

$ s='*'
$ ls $s.{ext1,ext2}
a.ext1  a.ext2  b.ext1  b.ext2

Hier hat die Befehlszeile Klammern, so dassKlammererweiterungkann als erster Schritt durchgeführt werden. Danach $swird der Wert von eingesetzt in (variable Erweiterung), und zuletztPfadnamenerweiterungist durchgeführt.

Dokumentation

man basherklärt die Reihenfolge der Erweiterung:

Die Reihenfolge der Erweiterungen ist: Klammernerweiterung, Tilde-Erweiterung, Parameter- und Variablenerweiterung, arithmetische Erweiterung und Befehlsersetzung (von links nach rechts durchgeführt), Worttrennung und Pfadnamenerweiterung.

verwandte Informationen