Eu tenho alguns nomes de arquivos contendo caracteres que são de controle especial regex.
Preciso preparar uma regex que considere todos esses caracteres literalmente.
Caso de teste simplificado:
strFilenameOnDB="some ( file ) name +.ok";
strFilenameToCheck="$strFilenameOnDB"; #code simplification
strRegex=".*${strFilenameToCheck}.*";
if [[ "$strFilenameOnDB" =~ $strRegex ]];then echo OK;fi
o acima (é claro) falhará.
em perl podemos usar /Q /E ( https://stackoverflow.com/a/3971923/1422630 ) para transformar o $strRegex expandido em literal, existe algo assim para o bash?
Obs.: Vou postar o que já estou fazendo, mas gostaria de saber se existe uma forma melhor?
Pessoalmente, eu não combinaria a string que você gostaria que fosse literal com os bits de expressão regular que você gostaria que fossem interpretados como padrão de expressão regular. O bit de string literal da expressão deve estar entre aspas duplas, os bits que precisam ser interpretados como uma expressão regular não devem ser.
Nesse caso, porém, como as expressões regulares não são ancoradas por padrão no início ou no final da string (ao contrário dos padrões de globbing de nome de arquivo que sempre correspondem a uma string completa ), você pode ficar sem o flanqueamento
.*
completamente.Você está apenas olhando para ver se o nome do arquivo contém uma substring específica? Porque se você fizer isso com
[[ =~ ]]
, você não precisará das.*
partes inicial e final: a correspondência regex é mais parecida com uma pesquisa , basta que uma correspondência seja encontrada em qualquer lugar da string.Além disso, no Bash, citar (partes do) padrão (ou uma variável que contém o padrão) remove os significados especiais dos caracteres citados. Então, por exemplo, isso corresponderia:
enquanto isso não (o plus é especial agora e não corresponde a si mesmo):
Em comparação, uma correspondência não regex exigirá correspondência com a string inteira, portanto, você precisa de uma inicial e uma final
*
:No operador match do Bash
=~
, strings literais na regex podem ser especificadas colocando-as entre aspas duplas.Então, em teoria, você só precisa transformar \Q e \E de Perl em uma aspa dupla cada.
Mas, no entanto, se seu requisito for usar um regex que seja parcialmente variável (ou seja, contenha outras variáveis de shell a serem expandidas) e parcialmente literal, e que esteja contido em uma variável de shell, temo que a única saída seja também usar
eval
. _Ou seja, seu código de exemplo ficaria assim:
Para resumir, para incorporar strings literais em um regex parcialmente variável contido em uma variável de shell, você precisa:
\"
e outro\"
no lugar do \Q e \E do Perleval
Tudo isso é necessário para expandir a string que contém o regex primeiro , para que os dois
"
na variável do shell sejam considerados como início e fim da parte literal do regex, em vez dos caracteres de cotação usuais do Bash e, em seguida, toda a operação de correspondência é executado em tal padrão resultante.(Uma tarefa bem mais difícil vem quando você precisa incluir aspas duplas ou barras invertidas em um regex dentro de uma variável de shell com aspas duplas..)
Como uma nota lateral, você realmente não precisa do
.*
início e do fim de um regex porque eles geralmente estão implícitos na operação regex do Bash. Na verdade, você precisa especificar explicitamente âncoras de início e fim (^
e$
) quando não quiser implicar outros caracteres antes e depois de uma regex.Eu mudo o matcher desta forma: