Следующий код
number=1
if [[ $number =~ [0-9] ]]
then
echo matched
fi
работает. Однако если я попытаюсь использовать кавычки в регулярном выражении, оно остановится:
number=1
if [[ $number =~ "[0-9]" ]]
then
echo matched
fi
Я тоже пробовал "\[0-9\]". Что мне не хватает?
Как ни странно, bash расширенное руководство по написанию сценариев предполагает, что это должно сработать.
Bash версии 3.2.39.





Был изменен между 3,1 и 3,2. Думаю, для расширенного руководства нужно обновление.
This is a terse description of the new features added to bash-3.2 since the release of bash-3.1. As always, the manual page (doc/bash.1) is the place to look for complete descriptions.
- New Features in Bash
snip
f. Quoting the string argument to the [[ command's =~ operator now forces string matching, as with the other pattern-matching operators.
К сожалению, это нарушит существующую цитату с использованием сценариев, если у вас нет понимания, как хранить шаблоны в переменных и напрямую использовать их вместо регулярных выражений. Пример ниже.
$ bash --version
GNU bash, version 3.2.39(1)-release (i486-pc-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.
$ number=2
$ if [[ $number =~ "[0-9]" ]]; then echo match; fi
$ if [[ $number =~ [0-9] ]]; then echo match; fi
match
$ re = "[0-9]"
$ if [[ $number =~ $re ]]; then echo MATCH; fi
MATCH
$ bash --version
GNU bash, version 3.00.0(1)-release (i586-suse-linux)
Copyright (C) 2004 Free Software Foundation, Inc.
$ number=2
$ if [[ $number =~ "[0-9]" ]]; then echo match; fi
match
$ if [[ "$number" =~ [0-9] ]]; then echo match; fi
match
Это настоящее развлечение. Цитированные регулярные выражения больше не работают. Регулярные выражения без кавычек с пробелами не работают. Регулярные выражения на основе переменных работают, даже если они содержат пробелы. Какой беспорядок.
Bash 3.2 представил параметр совместимости compat31, который возвращает поведение цитирования регулярных выражений bash обратно к 3.1.
Без compat31:
$ shopt -u compat31
$ shopt compat31
compat31 off
$ set -x
$ if [[ "9" =~ "[0-9]" ]]; then echo match; else echo no match; fi
+ [[ 9 =~ \[0-9] ]]
+ echo no match
no match
С compat31:
$ shopt -s compat31
+ shopt -s compat31
$ if [[ "9" =~ "[0-9]" ]]; then echo match; else echo no match; fi
+ [[ 9 =~ [0-9] ]]
+ echo match
match
Ссылка на патч: http://ftp.gnu.org/gnu/bash/bash-3.2-patches/bash32-039
GNU bash, версия 4.2.25 (1) -релиз (x86_64-pc-linux-gnu)
Некоторые примеры совпадений строк и регулярных выражений
$ if [[ 234 =~ "[0-9]" ]]; then echo matches; fi # string match
$
$ if [[ 234 =~ [0-9] ]]; then echo matches; fi # regex natch
matches
$ var = "[0-9]"
$ if [[ 234 =~ $var ]]; then echo matches; fi # regex match
matches
$ if [[ 234 =~ "$var" ]]; then echo matches; fi # string match after substituting $var as [0-9]
$ if [[ 'rss$var919' =~ "$var" ]]; then echo matches; fi # string match after substituting $var as [0-9]
$ if [[ 'rss$var919' =~ $var ]]; then echo matches; fi # regex match after substituting $var as [0-9]
matches
$ if [[ "rss\$var919" =~ "$var" ]]; then echo matches; fi # string match won't work
$ if [[ "rss\\$var919" =~ "$var" ]]; then echo matches; fi # string match won't work
$ if [[ "rss'$var'""919" =~ "$var" ]]; then echo matches; fi # $var is substituted on LHS & RHS and then string match happens
matches
$ if [[ 'rss$var919' =~ "\$var" ]]; then echo matches; fi # string match !
matches
$ if [[ 'rss$var919' =~ "$var" ]]; then echo matches; fi # string match failed
$
$ if [[ 'rss$var919' =~ '$var' ]]; then echo matches; fi # string match
matches
$ echo $var
[0-9]
$
$ if [[ abc123def =~ "[0-9]" ]]; then echo matches; fi
$ if [[ abc123def =~ [0-9] ]]; then echo matches; fi
matches
$ if [[ 'rss$var919' =~ '$var' ]]; then echo matches; fi # string match due to single quotes on RHS $var matches $var
matches
$ if [[ 'rss$var919' =~ $var ]]; then echo matches; fi # Regex match
matches
$ if [[ 'rss$var' =~ $var ]]; then echo matches; fi # Above e.g. really is regex match and not string match
$
$ if [[ 'rss$var919[0-9]' =~ "$var" ]]; then echo matches; fi # string match RHS substituted and then matched
matches
$ if [[ 'rss$var919' =~ "'$var'" ]]; then echo matches; fi # trying to string match '$var' fails
$ if [[ '$var' =~ "'$var'" ]]; then echo matches; fi # string match still fails as single quotes are omitted on RHS
$ if [[ \'$var\' =~ "'$var'" ]]; then echo matches; fi # this string match works as single quotes are included now on RHS
matches
Как упоминалось в других ответах, размещение регулярного выражения в переменной - это общий способ достижения совместимости с разными версиями трепать. Вы также можете использовать этот обходной путь для достижения того же результата, сохраняя свое регулярное выражение в условном выражении:
$ number=1
$ if [[ $number =~ $(echo "[0-9]") ]]; then echo matched; fi
matched
$
АБС довольно печально известна как источник неточных (или, в лучшие дни, просто вводящих в заблуждение) указаний; считайте это школой W3Schools сценариев оболочки. Рассматривайте bash-hackers.org или wooledge wiki как альтернативу, поддерживаемую с учетом точности.