Co tu zrobiłem źle?
Próba dopasowania dowolnego ciągu zawierającego spacje, małe litery, wielkie litery lub cyfry. Znaki specjalne też byłyby fajne, ale myślę, że wymaga to ucieczki przed niektórymi postaciami.
TEST="THIS is a TEST title with some numbers 12345 and special char *&^%$#"
if [[ "$TEST" =~ [^a-zA-Z0-9\ ] ]]; then BLAH; fi
To oczywiście sprawdza tylko górne, dolne, liczby i spacje. Ale to nie działa.
* AKTUALIZACJA *
Chyba powinienem był być bardziej szczegółowy. Oto rzeczywisty wiersz kodu.
if [[ "$TITLE" =~ [^a-zA-Z0-9\ ] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; fi
* AKTUALIZACJA *
./anm.sh: line 265: syntax error in conditional expression
./anm.sh: line 265: syntax error near `&*#]'
./anm.sh: line 265: ` if [[ ! "$TITLE" =~ [a-zA-Z0-9 $%^\&*#] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; return; fi'
regex
bash
if-statement
Atomiklan
źródło
źródło
re='...whatever...'; [[ $string =~ $re ]]
(bez cudzysłowów - to jeden z rzadkich przypadków, w których zepsują coś, co działałoby bez nich).[[ $var =~ .* ]]
for match regex.*
(cokolwiek). Myślę, że jeśli użyjesz cudzysłowów, same cytaty są uważane za część wyrażenia regularnego…pattern='^hello[0-9]*$'
(2.) w wyrażeniu z podwójnym kwadratem, jeśli potrzebujesz dopasowania wyrażenia regularnego, NIE cytuj wzorca, ponieważ cytowanie WYŁĄCZA dopasowanie do wzorca wyrażenia regularnego. (tj. wyrażenie[[ "$x" =~ $pattern ]]
będzie pasować przy użyciu wyrażenia regularnego, a wyrażenie[[ "$x" =~ "$pattern" ]]
wyłącza dopasowywanie wyrażeń regularnych i jest równoważne[[ "$x" == "$pattern" ]]
).Odpowiedzi:
Jest kilka ważnych rzeczy, które należy wiedzieć o
[[ ]]
konstrukcji basha . Pierwszy:Druga sprawa:
W związku z tym
$v
po obu stronach=~
zostanie rozwinięty do wartości tej zmiennej, ale wynik nie zostanie podzielony na słowa ani rozszerzony według nazwy ścieżki. Innymi słowy, pozostawienie rozszerzeń zmiennych bez cudzysłowów po lewej stronie jest całkowicie bezpieczne, ale trzeba wiedzieć, że rozszerzenia zmiennych będą występować po prawej stronie.Więc jeśli piszesz:
[[ $x =~ [$0-9a-zA-Z] ]]
The$0
wewnątrz regex po prawej stronie zostanie poszerzona przed regex jest interpretowany, co prawdopodobnie spowoduje regex niepowodzenie kompilacji (chyba ekspansji$0
kończy się cyfrą lub interpunkcyjny symbolu, którego wartość ASCII jest mniejsza niż cyfra). Jeśli w ten sposób zacytujesz prawą stronę[[ $x =~ "[$0-9a-zA-Z]" ]]
, to prawa strona będzie traktowana jako zwykły ciąg, a nie wyrażenie regularne (i$0
nadal będzie rozszerzana). To, czego naprawdę chcesz w tym przypadku, to[[ $x =~ [\$0-9a-zA-Z] ]]
Podobnie wyrażenie między
[[
i]]
jest dzielone na słowa przed interpretacją wyrażenia regularnego. Dlatego spacje w wyrażeniu regularnym muszą zostać zmienione lub cytowane. Jeśli chcesz, aby dopasować litery, cyfry lub spacje można użyć:[[ $x =~ [0-9a-zA-Z\ ] ]]
. Inne znaki podobnie muszą być poprzedzone znakami ucieczki, na przykład#
, które rozpoczynają komentarz, jeśli nie są cytowane. Oczywiście możesz umieścić wzorzec w zmiennej:pat="[0-9a-zA-Z ]" if [[ $x =~ $pat ]]; then ...
Wiele osób preferuje ten styl w przypadku wyrażeń regularnych zawierających wiele znaków, które musiałyby zostać usunięte lub zacytowane, aby przejść przez lekser basha. Ale uwaga: w tym przypadku nie możesz cytować rozwinięcia zmiennej:
# This doesn't work: if [[ $x =~ "$pat" ]]; then ...
Na koniec myślę, że to, co próbujesz zrobić, to sprawdzić, czy zmienna zawiera tylko prawidłowe znaki. Najłatwiejszym sposobem sprawdzenia tego jest upewnienie się, że nie zawiera nieprawidłowego znaku. Innymi słowy, wyrażenie takie jak to:
valid='0-9a-zA-Z $%&#' # add almost whatever else you want to allow to the list if [[ ! $x =~ [^$valid] ]]; then ...
!
neguje test, zamieniając go na operator „nie pasuje”, a[^...]
klasa znaku regex oznacza „dowolny znak inny niż...
”.Połączenie interpretacji parametrów i operatorów regex może sprawić, że składnia wyrażeń regularnych bash będzie „prawie czytelna”, ale nadal istnieje kilka problemów. (Nie są tam zawsze?) Jednym z nich jest, że nie można umieścić
]
w$valid
, nawet jeśli$valid
były notowane, z wyjątkiem samego początku. (To jest reguła wyrażenia regularnego Posix: jeśli chcesz dołączyć]
do klasy postaci, musi zaczynać się od początku.-
Może być na początku lub na końcu, więc jeśli potrzebujesz obu]
i-
, musisz zacząć]
i zakończyć-
, prowadząc do regex „wiem, co robię” emotikon:[][-]
)źródło
if ! [[ $x =~ $y ]]
alboif [[ ! $x =~ $y ]]
SC2076: Don't quote rhs of =~, it'll match literally rather than as a regex.
[[
i]]
” są usuwane z tekstu programu, w ten sam sposób, w jaki wiersze poleceń są przetwarzane na słowa. Jednak w przeciwieństwie do wierszy poleceń, słowa nie są dzielone po rozwinięciu.Na wypadek, gdyby ktoś chciał mieć przykład ze zmiennymi ...
#!/bin/bash # Only continue for 'develop' or 'release/*' branches BRANCH_REGEX="^(develop$|release//*)" if [[ $BRANCH =~ $BRANCH_REGEX ]]; then echo "BRANCH '$BRANCH' matches BRANCH_REGEX '$BRANCH_REGEX'" else echo "BRANCH '$BRANCH' DOES NOT MATCH BRANCH_REGEX '$BRANCH_REGEX'" fi
źródło
Wolałbym do tego użyć
[:punct:]
. Ponadto,a-zA-Z09-9
może być tylko[:alnum:]
:[[ $TEST =~ ^[[:alnum:][:blank:][:punct:]]+$ ]]
źródło