Em bash
3.2 ou superior e se a compatibilidade com 3.1 não estiver ativada (com a opção compat31
ou BASH_COMPAT=3.1
), citando operadores de expressões regulares (não apenas com \
mas com qualquer um dos bash
de operadores de cotação ( '...'
, "..."
, $'...'
, $"..."
)) remove seu significado especial.
[[ $var =~ 'OK$' ]]
corresponde apenas a strings que contêm OK$
literalmente (que $
corresponde a um literal $
)
[[ $var =~ OK$ ]]
corresponde a sequências que terminam em OK
(que $
é o operador RE que corresponde ao final da sequência).
Isso também se aplica a regexps armazenados em variáveis ou o resultado de alguma substituição.
[[ $var =~ $regexp ]] # $var matches $regexp
[[ $var =~ "$string" ]] # $var contains $string
Note que pode tornar-se complicado porque existem alguns caracteres que você precisa citar para a sintaxe do shell (como espaços em branco, <
, >
, &
, parênteses quando não correspondidos). Por exemplo, se você deseja corresponder à .{3} <> [)}]&
regexp (3 caracteres seguidos por " <> "
, )
ou }
e &
), é necessário algo como:
[[ $var =~ .{3}" <> "[}\)]\& ]]
Se tiver dúvidas sobre quais caracteres precisam ser citados, você sempre pode usar uma variável temporária . Isso também significa que ele tornará o código compatível com bash31
, zsh
ou ksh93
:
pattern='.{3} <> [})]&'
[[ $var =~ $pattern ]] # remember *not* to quote $pattern here
Essa também é a única maneira (além de usar a opção compat31
(ou BASH_COMPAT=3.1
)) você pode fazer uso dos operadores estendidos não POSIX dos regexps do seu sistema.
Por exemplo, para que \<
seja tratado como o limite de palavras que está em muitos mecanismos de expressão regular, você precisa:
pattern='\<word\>'
[[ $var =~ $pattern ]]
Fazendo:
[[ $var =~ \<word\> ]]
não funciona, pois bash
trata esses \
como operadores de criação de shell e tira-os antes de passar <word>
para a biblioteca regexp.
Note que é muito pior em ksh93 onde:
[[ $var =~ "x.*$" ]]
Por exemplo, corresponderá a whatever-xa*
, mas não a whatever-xfoo
. A citação acima remove o significado especial para *
, mas não para .
nem $
.
O comportamento zsh
é mais simples: as cotações não alteram o significado dos operadores regexp (como em bash31), o que contribui para um comportamento mais previsível (também pode usar regexps PCRE em vez de ERE (com set -o rematchpcre
) ).
yash
não tem uma construção [[...]]
, mas seu [
builtin tem um operador =~
(também em zsh
). E, claro, [
sendo um comando normal, a cotação não pode afetar a maneira como os operadores regexp são interpretados.
Observe também que, estritamente falando, o $s
não contém 3 linhas, mas 2 linhas completas seguidas por uma linha não terminada. Contém hello\nworld\nOK
. Na expressão regular estendida OK$
, o operador $
corresponderia apenas ao final da string .
Em uma sequência de 3 linhas completas , como hello\nworld\nOK\n
(que você não seria capaz de obter com a substituição de comandos, como tiras de substituição de comandos all caracteres), o $
corresponderia após o \n
, portanto, OK$
não corresponderia a ele.
Com zsh -o pcrematch
, no entanto, o $
corresponde ao final da string e à nova linha no final da string, se houver uma, pois ela não passa o PCRE_DOLLAR_ENDONLY
para pcre_compile
. Isso pode ser visto como uma má idéia, geralmente, variáveis em shells não contêm um caractere de nova linha, e quando eles geralmente querem que eles sejam considerados dados .