Chciałbym powiedzieć, czy ciąg $string
pasowałby do wzorca globu $pattern
. $string
może, ale nie musi, być nazwą istniejącego pliku. W jaki sposób mogę to zrobić?
Przyjmij następujące formaty dla moich ciągów wejściowych:
string="/foo/bar"
pattern1="/foo/*"
pattern2="/foo/{bar,baz}"
Chciałbym znaleźć idiom bash, który określa, czy $string
będzie dopasowane $pattern1
, $pattern2
lub jakiegokolwiek innego arbitralnego glob wzorca. Oto, co próbowałem do tej pory:
[[ "$string" = $pattern ]]
To prawie działa, ale
$pattern
jest interpretowane jako wzorzec łańcucha, a nie jako wzorzec globalny.[ "$string" = $pattern ]
Problem z tym podejściem polega na tym, że
$pattern
jest on rozwijany, a następnie przeprowadzane jest porównywanie ciągów znaków$string
z rozszerzeniem$pattern
.[[ "$(find $pattern -print0 -maxdepth 0 2>/dev/null)" =~ "$string" ]]
Ten działa, ale tylko wtedy, gdy
$string
zawiera plik, który istnieje.[[ $string =~ $pattern ]]
To nie działa, ponieważ
=~
operator powoduje$pattern
interpretację jako rozszerzone wyrażenie regularne, a nie wzorzec globalny lub symbol wieloznaczny.
{bar,baz}
to nie jest wzór. To rozszerzenie parametrów. Subtelna, ale krytyczna różnica w tym{bar,baz}
jest bardzo wcześnie rozszerzona na wiele argumentówbar
ibaz
.ls /foo/*
teraz możesz dopasowaćfoo/{bar,baz}
tak naprawdę jest to rozwinięcie nawiasów klamrowych (a nie rozszerzenie parametrów), podczas gdyfoo/*
jest to rozwinięcie nazwy ścieżki.$string
to rozszerzenie parametrów. Wszystko to odbywa się w różnym czasie i za pomocą różnych mechanizmów.case
instrukcja wykonuje rozszerzenie nazwy ścieżki („globbing”) zgodnie z instrukcją Bash.Odpowiedzi:
Nie ma ogólnego rozwiązania tego problemu. Powodem jest to, że w bash, rozwijanie nawiasów (tj.
{pattern1,pattern2,...}
I rozwijanie nazw plików (inaczej wzorce glob) są uważane za osobne rzeczy i rozwijane w różnych warunkach i w różnych czasach. Oto pełna lista rozszerzeń, które wykonuje bash:Ponieważ troszczymy się tylko o ich podzbiór (być może rozwinięcie nawiasu klamrowego, tyldy i ścieżki), możliwe jest użycie pewnych wzorców i mechanizmów w celu ograniczenia ekspansji w kontrolowany sposób. Na przykład:
Uruchomienie tego skryptu generuje następujące dane wyjściowe:
Działa to, ponieważ
set -f
wyłącza interpretację nazw ścieżek, dlatego w instrukcji występują tylko interpretacja nawiasów i interpretacja tyldyfor pattern in /foo/{*,foo*,bar*,**,**/*}
. Następnie możemy użyć operacji testowej,[[ $string == $pattern ]]
aby przetestować interpretację ścieżki po tym, jak interpretacja nawiasu została już wykonana.źródło
Nie wierzę, że
{bar,baz}
jest to wzór globu powłoki (choć z pewnością tak/foo/ba[rz]
jest), ale jeśli chcesz wiedzieć, czy$string
dopasowania$pattern
możesz zrobić:Możesz zrobić tyle, ile chcesz:
źródło
{bar,baz}
nie jest globalnym wzorcem. Już znalazłem rozwiązanie mojego pytania, które bierze to pod uwagę.Jak zauważył Patrick, potrzebujesz „innego rodzaju” wzoru:
Cytaty nie są tam konieczne.
źródło
sed
operacja.W ten sposób użyłbym grep:
Co daje wynik:
źródło
w zsh:
źródło