Соответствие регулярному выражению в операторе bash if

что я сделал не так здесь?

попытка сопоставить любую строку, содержащую пробелы, нижний регистр, верхний регистр или числа. Специальные символы тоже были бы хороши, но я думаю, что для этого требуется избежать определенных символов.

TEST="THIS is a TEST title with some numbers 12345 and special char *&^%$#"

if [[ "$TEST" =~ [^a-zA-Z0-9 ] ]]; then BLAH; fi

это, очевидно, только тесты для верхних, нижних, чисел и пробелов. Не сработало.

* обновление *

думаю, я должен был быть более конкретным. Вот реальной линии код.

if [[ "$TITLE" =~ [^a-zA-Z0-9 ] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; fi

* обновление *

./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'

3 ответов


есть несколько важных вещей, чтобы знать о Баша [[ ]] строительство. Первое:

разделение слов и расширение пути не выполняются для слов между [[ и ]]; расширение Тильды, расширение параметра и переменной, арифметическое расширение, замена команды, замена процесса и удаление цитаты выполнены.

второе:

дополнительный двоичный оператор, ‘=~’, имеющийся.,.. строка справа от оператора считается расширенным регулярным выражением и соответствующим образом сопоставляется... любая часть шаблона может быть процитирована, чтобы заставить ее соответствовать в виде строки.

следовательно, $v по обе стороны =~ будет расширено до значения этой переменной,но результат не будет разделен словом или расширен путем. Другими словами, совершенно безопасно оставлять переменные расширения без кавычек левая сторона, но вам нужно знать, что переменные расширения будут происходить с правой стороны.

Итак, если вы пишете: [[ $x =~ [-9a-zA-Z] ]] на внутри регулярного выражения справа будет расширено до интерпретации регулярного выражения, что, вероятно, приведет к сбою компиляции регулярного выражения (если только расширение заканчивается цифрой или символом пунктуации, значение ascii которого меньше цифры). если вы цитируете правую сторону, как-так [[ $x =~ "[-9a-zA-Z]" ]], затем правая сторона будет рассматриваться как обычная строка, а не регулярное выражение все равно будет расширен). Что вы действительно хотите в этом случае [[ $x =~ [$0-9a-zA-Z] ]]

аналогично, выражение между [[ и ]] разбивается на слова перед интерпретацией регулярного выражения. Поэтому пробелы в регулярном выражении должны быть экранированы или процитированы. Если вы хотите сопоставить буквы, цифры или пробелы, вы можете использовать:[[ $x =~ [0-9a-zA-Z\ ] ]]. Другие символы также должны быть экранированы, например #, который начнет комментарий если не цитируется. Конечно, вы можете поместить шаблон в переменную:

pat="[0-9a-zA-Z ]"
if [[ $x =~ $pat ]]; then ...

для регулярных выражений, содержащих множество символов, которые нужно было бы экранировать или процитировать, чтобы пройти через лексер bash, многие люди предпочитают этот стиль. Но будьте осторожны: в этом случае вы не может процитируйте расширение переменной:

# This doesn't work:
if [[ $x =~ "$pat" ]]; then ...

наконец, я думаю, что вы пытаетесь проверить, что переменная содержит только допустимые символы. Самый простой способ сделать это проверить чтобы убедиться, что он не содержит недопустимый символ. Другими словами, такое выражение:

valid='0-9a-zA-Z $%&#' # add almost whatever else you want to allow to the list
if [[ ! $x =~ [^$valid] ]]; then ...

! отрицает тест, превращая его в оператор" не соответствует " и [^...] regex класс символов означает " любой символ, кроме ...".

комбинация операторов расширения параметров и регулярных выражений может сделать синтаксис регулярного выражения bash "почти читаемым", но все еще есть некоторые gotchas. (Разве не всегда?) Во-первых, что вы не мог поставить ] на $valid, даже если $valid были процитированы, за исключением самого начала. (Это правило POSIX regex: если вы хотите включить ] в классе символов он должен идти в начале. - может идти в начале или в конце, так что если вам нужно оба ] и -, вам нужно начать с ] и -, что приводит к регулярному выражению" я знаю, что делаю " смайлик:[][-])


Я бы предпочел использовать [:punct:] для этого. Кроме того,a-zA-Z09-9 может быть только [:alnum:]:

[[ $TEST =~ ^[[:alnum:][:blank:][:punct:]]+$ ]]

в случае, если кто-то хотел пример использования переменных...

#!/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