Есть несколько важных вещей, которые нужно знать о [[ ]]
конструкции 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: если вы хотите включить ]
в класс символов, он должен идти в начале. -
Может идти в начале или в конце, поэтому, если вам нужны оба ]
и -
, вам нужно начинать ]
и заканчивать с -
, что приводит к регулярному выражению «Я знаю , что я делаю» смайлик: [][-]
)