bash expressão condicional e escape de barra invertida

Oct 30 2020

É muito difícil entender este comportamento:

stackExchange@test:~$ if [[ "two words" =~ \bwords ]]; then echo hi; fi; #(I'd expect this one worked) stackExchange@test:~$ if [[ "two words" =~ \\bwords ]]; then echo hi; fi; #(or at least this one...)
stackExchange@test:~$ if [[ "two words" =~ \\\bwords ]]; then echo hi; fi; stackExchange@test:~$ if [[ "two words" =~ \\\\bwords ]]; then echo hi; fi;
stackExchange@test:~$ put_in_a_variable=\\bwords stackExchange@test:~$ if [[ "two words" =~ $put_in_a_variable ]]; then echo hi; fi; hi stackExchange@test:~$

Eu entendo que minha variável contém \bworde isso foi expandido na seção de padrão da expressão condicional, mas eu realmente não consigo entender por que parece impossível atingir o mesmo comportamento usando escape de shell embutido.

Eu não quero fazer algo assim if [[ "two words" =~ $(echo \\bwords) ]]; then echo hi; fi;; Muito estranho...

Obrigada
Francesco

Respostas

2 user414777 Oct 30 2020 at 01:33

O efeito de uma barra invertida na parte da expressão regular de [[ str =~ rex ]]é citar o caractere a seguir (exatamente como colocá-lo entre aspas simples), o que direcionaria o bash a fazer uma correspondência literal para ele (1). Como bnão é especial, \bse tornará justo b, mas '\', "\\"ou \\se tornará \\para corresponder a uma barra invertida literal:

[[ abwords =~ \bwords ]] && echo "<$BASH_REMATCH>" <bwords> [[ 'a\bwords' =~ \\bwords ]] && echo "<$BASH_REMATCH>"
<\bwords>
# conversely, '|' is just like \|
[[ 'a|words' =~ a'|'words ]] && echo "<$BASH_REMATCH>"
<a|words>

Sua ideia de colocar a regex em uma variável é boa. Uma alternativa seria usar uma função de wrapper:

rematch() [[ $1 =~ $2 ]] if rematch 'two words' '\bwords\b'; then echo "<$BASH_REMATCH>"
fi
<words>

(1): conforme documentado em seu manual :

Qualquer parte do padrão pode ser citada para forçar a parte citada a ser combinada como uma string

Observe que, no shell, os caracteres que estão entre aspas são realmente marcados de maneira especial , de modo que qualquer processamento subsequente pelo analisador pode basear as decisões em se uma parte de uma string foi citada ou não.