Я пытаюсь определить, содержит ли строка регулярное выражение в оболочке (bash).
В частности, если он содержит цифру.
И пока это:

$ [[ string_with[6]indice =~ [0-9] ]] && echo "True" || echo "False"

работает как положено, когда я назначаю LHS и RHS переменным, происходит нечто странное:

$ STR=string_with[6]indice
$ REGEX=[0-9]
$ [[ string_with[6]indice =~ [0-9] ]] && echo "True" || echo "False"
False

Я хотел посмотреть, на что shell расходует мои переменные, и выяснил это:

$ STR=string_with[6]indice
+ STR='string_with[6]indice'
$ REGEX=[0-9]
+ REGEX='[0-9]'
$ [[ $STR =~ "$REGEX" ]] && echo "True" || echo "False"
+ [[ string_with[6]indice =~ \[0-9] ]]
+ echo False
False

Откуда это \ перед [0-9] и почему оболочка автоматически экранирует первую скобку [ в REGEX?

1 ответ1

1

Это потому что у вас двойные кавычки около $REGEX . При сопоставлении с оператором =~ цитируемые разделы шаблона обрабатываются буквально. То есть метасимволы регулярных выражений в цитируемых разделах обрабатываются так, как если бы они были экранированы. Сравните эффект, когда шаблон в кавычках:

$ # Pattern in variable, quoted:
$ [[ $STR =~ "$REGEX" ]] && echo "True" || echo "False"
+ [[ string_with[6]indice =~ \[0-9] ]]
+ echo False
False
$ # Pattern directly in command, quoted:
$ [[ $STR =~ "[0-9]" ]] && echo "True" || echo "False"
+ [[ string_with[6]indice =~ \[0-9] ]]
+ echo False
False

с эффектом без кавычек:

$ # Pattern in variable, NOT quoted:
$ [[ $STR =~ $REGEX ]] && echo "True" || echo "False"
+ [[ string_with[6]indice =~ [0-9] ]]
+ echo True
True
$ # Pattern directly in command, NOT quoted:
$ [[ $STR =~ [0-9] ]] && echo "True" || echo "False"
+ [[ string_with[6]indice =~ [0-9] ]]
+ echo True
True

Это один из немногих случаев, когда вы не хотите заключать в кавычки переменную.

Кстати, я рекомендую использовать строчные или смешанные имена переменных в сценариях оболочки; таким образом вы не рискуете конфликтовать с какой-либо переменной среды, которая имеет особое значение для оболочки или других программ (классический пример - $PATH ).

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .