Есть несколько важных вещей, которые нужно знать о [[ ]]конструкции bash . Первое:
Разделение слов и расширение имени пути не выполняется для слов между символами [[и ]]; Выполняются раскрытие тильды, раскрытие параметров и переменных, арифметическое раскрытие, подстановка команд, подстановка процессов и удаление кавычек.
Второе:
Доступен дополнительный бинарный оператор '= ~', ... строка справа от оператора считается расширенным регулярным выражением и соответствующим образом сопоставляется ... Любая часть шаблона может быть заключена в кавычки, чтобы заставить ее сопоставить в виде строки .
Следовательно, $vс обеих сторон =~будет расширено до значения этой переменной, но результат не будет разбит по словам или расширен по имени пути. Другими словами, совершенно безопасно оставлять расширения переменных без кавычек с левой стороны, но вы должны знать, что расширения переменных будут происходить с правой стороны.
Так что если вы пишете: [[ $x =~ [$0-9a-zA-Z] ]], то $0в регулярном выражении по праву будет расширены до регулярного выражения интерпретируется, который, вероятно , вызовет регулярное выражение , чтобы не компилировать (если не указано расширение $0целей с символом цифр или знаков препинания , чье ASCII значения меньше цифра). Если вы процитируете правую часть таким образом [[ $x =~ "[$0-9a-zA-Z]" ]], то правая часть будет рассматриваться как обычная строка, а не как регулярное выражение (и $0все равно будет расширена). Что вам действительно нужно в этом случае, так это[[ $x =~ [\$0-9a-zA-Z] ]]
Точно так же выражение между [[и ]]разбивается на слова перед интерпретацией регулярного выражения. Поэтому пробелы в регулярном выражении необходимо экранировать или заключать в кавычки. Если вы хотите , чтобы соответствовать буквы, цифры и пробелы вы можете использовать: [[ $x =~ [0-9a-zA-Z\ ] ]]. Другие символы также должны быть экранированы, например #, если они не указаны в кавычках, начнется комментарий. Конечно, вы можете поместить шаблон в переменную:
pat="[0-9a-zA-Z ]"
if [[ $x =~ $pat ]]; then ...
Многие люди предпочитают этот стиль для регулярных выражений, которые содержат множество символов, которые необходимо экранировать или заключать в кавычки для прохождения через лексер bash. Но будьте осторожны: в этом случае вы не можете указывать расширение переменной:
if [[ $x =~ "$pat" ]]; then ...
Наконец, я думаю, что вы пытаетесь проверить, что переменная содержит только допустимые символы. Самый простой способ выполнить эту проверку - убедиться, что он не содержит недопустимого символа. Другими словами, такое выражение:
valid='0-9a-zA-Z $%&#'
if [[ ! $x =~ [^$valid] ]]; then ...
!отменяет тест, превращая его в оператор «не соответствует», а [^...]класс символов регулярного выражения означает «любой символ кроме ...».
Комбинация операторов расширения параметров и регулярных выражений может сделать синтаксис регулярных выражений bash «почти читаемым», но все же есть некоторые подводные камни. (Не существует всегда?) Во- первых, вы не могли бы поставить ]в $valid, даже если $validбыли указаны, за исключением самого начала. (Это правило регулярного выражения Posix: если вы хотите включить ]в класс символов, он должен идти в начале. -Может идти в начале или в конце, поэтому, если вам нужны оба ]и -, вам нужно начинать ]и заканчивать с -, что приводит к регулярному выражению «Я знаю , что я делаю» смайлик: [][-])