Ich würde gerne sagen, ob ein String $string
mit einem Glob-Muster übereinstimmt $pattern
. $string
kann oder kann nicht der Name einer vorhandenen Datei sein. Wie kann ich das machen?
Angenommen, die folgenden Formate für meine Eingabezeichenfolgen:
string="/foo/bar"
pattern1="/foo/*"
pattern2="/foo/{bar,baz}"
Ich möchte eine bash Idiom finden, wenn bestimmt $string
würde durch abgestimmt werden $pattern1
, $pattern2
oder jedem anderen beliebigen glob Muster. Folgendes habe ich bisher versucht:
[[ "$string" = $pattern ]]
Dies funktioniert fast, außer dass dies
$pattern
als String-Muster und nicht als Glob-Muster interpretiert wird.[ "$string" = $pattern ]
Das Problem bei diesem Ansatz ist, dass
$pattern
erweitert wird und dann ein Zeichenfolgenvergleich zwischen$string
und der Erweiterung von durchgeführt wird$pattern
.[[ "$(find $pattern -print0 -maxdepth 0 2>/dev/null)" =~ "$string" ]]
Dieser funktioniert, aber nur, wenn er
$string
eine Datei enthält, die existiert.[[ $string =~ $pattern ]]
Dies funktioniert nicht, da der
=~
Operator bewirkt$pattern
, dass er als erweiterter regulärer Ausdruck interpretiert wird, nicht als Glob- oder Platzhaltermuster.
{bar,baz}
es sich nicht um ein Muster handelt. Es ist eine Parametererweiterung. Dezent , aber entscheidender Unterschied, dass{bar,baz}
sehr früh erweitert auf in mehrere Argumente,bar
undbaz
.ls /foo/*
foo/{bar,baz}
es sich tatsächlich um eine Klammererweiterung (keine Parametererweiterung) handelt, währendfoo/*
es sich um eine Pfadnamenerweiterung handelt.$string
ist Parametererweiterung. Dies alles geschieht zu unterschiedlichen Zeiten und durch unterschiedliche Mechanismen.case
erzielen möchten , führt die Anweisung die Pfadnamenerweiterung ("Globbing") gemäß dem Bash-Handbuch aus.Antworten:
Für dieses Problem gibt es keine allgemeine Lösung. Der Grund dafür ist, dass geschweifte Klammern (dh
{pattern1,pattern2,...}
und Dateinamen (auch Glob-Muster genannt)) unter verschiedenen Bedingungen und zu verschiedenen Zeiten als separate Elemente betrachtet werden. Hier ist die vollständige Liste der von bash durchgeführten Erweiterungen:Da wir uns nur um eine Teilmenge dieser Elemente kümmern (z. B. die Erweiterung von Klammern, Tilden und Pfadnamen), können bestimmte Muster und Mechanismen verwendet werden, um die Erweiterung auf kontrollierbare Weise einzuschränken. Zum Beispiel:
Das Ausführen dieses Skripts generiert die folgende Ausgabe:
Dies funktioniert, weil
set -f
die Pfadnamenerweiterung deaktiviert ist, sodass in der Anweisung nur die Klammererweiterung und die Tildeerweiterung erfolgenfor pattern in /foo/{*,foo*,bar*,**,**/*}
. Mit der Testoperation können wir dann[[ $string == $pattern ]]
gegen die Pfadnamenerweiterung testen, nachdem die geschweifte Klammer bereits ausgeführt wurde.quelle
Ich glaube nicht , dass
{bar,baz}
ist ein Shell - Glob - Muster (obwohl sicher/foo/ba[rz]
ist) , aber wenn Sie wissen wollen , ob$string
Streichhölzer$pattern
Sie tun können:Sie können so viele machen, wie Sie möchten:
quelle
{bar,baz}
kein Glob-Muster ist. Ich habe bereits eine Lösung für meine Frage gefunden, die dies berücksichtigt.Wie Patrick betonte, brauchst du eine "andere Art" von Muster:
Anführungszeichen sind dort nicht erforderlich.
quelle
sed
Operation.Ich würde grep so benutzen:
Welches gibt die Ausgabe:
quelle
in zsh:
quelle