Próbuję użyć zmiennej składającej się z różnych ciągów znaków oddzielonych |
za pomocą case
testu instrukcji. Na przykład:
string="\"foo\"|\"bar\""
read choice
case $choice in
$string)
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Chcę być w stanie wpisać foo
lub bar
wykonać pierwszą część case
instrukcji. Jednak oba foo
i bar
zabierzcie mnie do drugiego:
$ foo.sh
foo
Bad choice!
$ foo.sh
bar
Bad choice!
Używanie "$string"
zamiast $string
nie robi różnicy. Nie używa też string="foo|bar"
.
Wiem, że mogę to zrobić w ten sposób:
case $choice in
"foo"|"bar")
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Mogę wymyślić różne obejścia, ale chciałbym wiedzieć, czy można użyć zmiennej jako case
warunku w bash. Czy to możliwe, a jeśli tak, to w jaki sposób?
bash
shell-script
case
terdon
źródło
źródło
eval
, uciekając $ wybór, nawiasy, gwiazdka, średników i znaków nowej linii. Brzydkie, ale „działa”.read
kawałek mnie powstrzymał. Moim zdaniem sprawdzanie poprawności danych wejściowych przez użytkownika, czyli takie, jak się wydaje,case
wzorce nie powinny znajdować się na górze listy oceny, a raczej powinny być przycinane do*
domyślnego wzorca, tak aby zagwarantować, że jedyne osiągnięte wyniki są gwarantowane. nadal, ponieważ problemem jest kolejność parsowania / rozbudowy, może być potrzebna druga ocena.Odpowiedzi:
Instrukcja bash stwierdza:
Brak «rozszerzenia nazwy ścieżki»
Zatem: wzorzec NIE jest rozwijany za pomocą «Rozwinięcia nazwy ścieżki».
Dlatego: wzorzec NIE może zawierać „|” wewnątrz. Tylko: dwa wzorce można połączyć za pomocą „|”.
To działa:
Używanie «rozszerzonego globowania»
Jest to jednak
word
zgodne zpattern
użyciem reguł «Rozszerzenie nazwy ścieżki».I «Extended Globbing» tutaj , tutaj i tutaj pozwala na stosowanie naprzemiennych wzorów („|”).
Działa to również:
Treść ciągu
Następny skrypt testowy pokazuje, że wzorzec pasujący do wszystkich wierszy zawierających jeden
foo
lubbar
gdziekolwiek jest'*$(foo|bar)*'
albo dwie zmienne$s1=*foo*
i$s2=*bar*
Skrypt testowy:
źródło
Możesz użyć
extglob
opcji:źródło
@(foo|bar)
na tle innychfoo|bar
? Oba są poprawnymi wzorcami, które działają tak samo, gdy są pisane dosłownie.|
nie jest częścią wzorcafoo|bar
, jest częścią składnicase
instrukcji pozwalającej na stosowanie wielu wzorców w jednej klauzuli.|
jest jednak częścią rozszerzonego wzorca.Potrzebujesz dwóch zmiennych,
case
ponieważ or lub|
potok są analizowane przed rozwinięciem wzorców.Wzory powłoki w zmiennych są obsługiwane inaczej, gdy są cytowane lub nie są cytowane:
źródło
Jeśli chcesz obejść interfejs zgodny z deską rozdzielczą, możesz napisać:
Objaśnienie: awk służy do podziału „łańcucha” i testowania każdej części osobno. Jeśli „wybór” pasuje do aktualnie testowanej części p [i], polecenie awk zostanie zakończone z „wyjściem” w wierszu 11. Do samego testu używana jest „wielkość liter” powłoki (w wywołaniu „systemowym”) , jak zapytał terdon. Dzięki temu istnieje możliwość modyfikacji zamierzonego „łańcucha” testowego, na przykład „foo * | bar”, aby pasował również do „foooo” („wzorzec wyszukiwania”), na co pozwala „wielkość liter” powłoki. Jeśli zamiast tego wolisz wyrażenia regularne, możesz pominąć wywołanie „systemowe” i zamiast tego użyć „~” lub „dopasuj” awk.
źródło