Quais métodos de expressão regular para validar a entrada podem ser usados em scripts de shell?

5
#!/bin/sh

re="\/$"

if [ $1 =~ $re ]; then
        echo "${ATTENTION_PREFIX}$1 DIRECTORY MAY NOT CONTAIN A \"/\" OR LITERAL SLASH!${ATTENTION_POSTFIX}"
        exit 1
fi

A execução de sudo file.sh hello/ resulta em [: 29: hello: unexpected operator

Parece que esse método de expressão regular está incorreto para scripts de shell.

    
por 030 04.07.2014 / 10:22

3 respostas

8

O comando padrão test , também conhecido como [ , não possui um operador =~ . A maioria das shells tem esse comando embutido hoje em dia.

O shell Korn introduziu uma construção [[...]] (não um comando [[ ) com sintaxe alternativa e regras de análise diferentes.

zsh e bash copiaram que, até certo ponto, com restrições e muitas diferenças, mas que nunca foram padronizadas, não devem ser usadas em scripts sh portáteis.

ksh93 sempre teve uma maneira de converter um regexp estendido em seus globs com:

printf '%P\n' "regexp"

E você poderia fazer:

[[ $var = pattern ]]

Mais tarde (em algum momento entre 2001 e 2003) também incorporou expressões regulares em seus globs como na sintaxe ~(E)regex para expressões regulares estendidas, então você pode fazer:

[[ $var = ~(E)pattern ]]

Esse tipo de correspondência de padrões funciona apenas com o comando [[...]] ou case , não o [ .

zsh adicionou um operador de correspondência de expressões regulares para o comando [ e [[...]] primeiro em 2001 com um módulo pcre . A sintaxe foi inicialmente [ string -pcre-match regex ] ou [[ string -pcre-match regex ]] .

bash adicionou um operador =~ no bash 3.0 (em 2004). Usando expressões regulares estendidas. Isso foi adicionado logo depois por ksh93 e zsh também (novamente com diferenças).

ksh93 e bash-3.1 e acima usam aspas para o escape operador regexp causando todos os tipos de confusão e significando que não pode ser usado com o comando [ lá. zsh não tem esse problema (aspas são usadas para aspas shell e backslash para escapar do operador regex como de costume), então o operador =~ trabalha no comando zsh [ (embora ele próprio precise ser citado desde =foo é um operador globbing em zsh ).

yash (um pequeno shell POSIX) não tem [[...]] , mas seu comando [ tem um operador =~ (usando EREs) e funciona como esperado (como zsh 's) .

Em qualquer caso, nem [[...]] nem =~ são POSIX e devem ser usados em sh scripts. O comando padrão para fazer correspondência de expressões regulares em strings é expr :

if expr "x$var" : "x$regex" > /dev/null; then...

Observe que% regexpsexpr estão ancorados no início e você precisa do truque x para evitar problemas com $var valores que são expr operadores.

Na maioria das vezes, você não precisa de regexp, já que a correspondência simples de padrões de shell é suficiente para a maioria dos casos:

case $var in
  (pattern) echo matches
esac
    
por 04.07.2014 / 11:58
5

Altere #!/bin/sh para #!/bin/bash e use colchetes duplos:

if [[ $1 =~ $re ]]; then

Este é o comando de teste estendido, em oposição ao comando de teste (regular). =~ só pode ser usado com a versão [[ ... ]] e requer o Bash 3.0 ou posterior.

    
por 04.07.2014 / 10:30
5

Em bash old test [ não suporta regex. Você deve usar o novo teste [[ :

re="\/$"

if [[ $1 =~ $re ]]; then
        echo "${ATTENTION_PREFIX}$1 DIRECTORY MAY NOT CONTAIN A \"/\" OR LITERAL SLASH!${ATTENTION_POSTFIX}"
        exit 1
fi

Você pode ver mais aqui .

Você também precisará alterar sua linha #!/bin/sh shebang para #!/bin/bash .

    
por 04.07.2014 / 10:31