String correspondência de padrões com = ~

4

Eu tenho problemas para entender a correspondência do padrão de string com = ~ em bash .

Eu escrevi a seguinte função (não se assuste - é só experimentar, não uma abordagem de segurança com o md5sum):

md5 ()  { 
     [[ "$(md5sum $1)" =~ $2* ]] && echo fine || echo baarr; 
}

e testado com alguma entrada. Aqui alguma referência:

md5sum wp.laenderliste
b1eb0d822e8d841249e3d68eeb3068d3  wp.laenderliste

É desnecessariamente difícil comparar, se a origem da soma de controle não contiver os dois espaços em branco com o nome do arquivo já. É de onde as observações se originam, mas mais interessante do que as muitas maneiras de resolver esse problema foi minha observação:

Eu defino uma variável de controle e testo minha função com strings muito curtas, mas correspondentes:

ok=b1eb0d822e8d841249e3d68eeb3068d3
for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i} ;done 
fine
fine
fine
fine

Isso é esperado e bom, já que é o propósito da função, ignorar a incompatibilidade da falta de "wp.laenderliste" e, portanto, incompatibilidades ainda mais longas.

Agora, se eu acrescentar coisas aleatórias, o que não combina, eu espero, é claro, erros, e pegue-os:

for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}GU ;done 
baarr
baarr
baarr
baarr

Como esperado. Mas quando há apenas um último caractere incompatível , veja o que acontece:

for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}G ;done 
fine
fine
fine
fine

É este eu, não percebendo como isso deve funcionar (select is broken), ou há realmente um erro off-by-one na correspondência de padrões do bash?

Incompatibilidades no meio da string importam da contagem 1:

for i in 5 9 e ; do echo md5 wp.laenderliste ${ok//$i/_} ;done 
md5 wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3
md5 wp.laenderliste b1eb0d822e8d84124_e3d68eeb3068d3
md5 wp.laenderliste b1_b0d822_8d841249_3d68__b3068d3

for i in 5 9 e ; do md5 wp.laenderliste ${ok//$i/_} ;done 
fine
baarr
baarr

A versão bash:

bash -version
GNU bash, Version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
Lizenz GPLv3+: GNU GPL Version 3 oder jünger <http://gnu.org/licenses/gpl.html>

Disclaimer : md5sum é apenas útil contra erros não intencionais, não contra ataques. Eu não encorajo usá-lo.

E esta questão não é uma busca por melhores soluções ou soluções alternativas. É sobre o operador = ~ , se deve agir como tal e, em caso afirmativo, porquê.

    
por user unknown 09.01.2018 / 15:38

2 respostas

9

=~ in ( [[ ]] ) é uma correspondência de padrão de expressão regular (ou melhor, uma pesquisa , veja abaixo). Isso é diferente de = (ou == ), que usa os mesmos padrões dos caracteres curinga de nome de arquivo.

Em particular, o asterisco em expressões regulares significa "zero ou uma cópia da unidade anterior", portanto abc* significa ab mais zero ou mais c s.

No seu caso, o asterisco final torna o caractere final do argumento de função opcional. No seu exemplo final, o padrão se torna ...68d3G* e, como G* corresponde à string vazia, ele corresponde a uma string como ...68d3 . Regexese para "qualquer string" é de .* , ou "qualquer caractere, qualquer número de vezes".

Observe que a correspondência de expressão regular procura uma correspondência em qualquer lugar da sequência, não precisa ser a sequência inteira . Então, o padrão cde seria encontrado na string abcdefgh .

Você pode querer usar algo assim:

[[ "$(md5sum "$1")" = "$2 "* ]] && echo ok

Realmente não precisamos de uma correspondência de expressão regular aqui, e como md5sum produz o espaço à direita (mais nome de arquivo), podemos usar isso no padrão para verificar se combinamos com o padrão completo. Então, dar à função um hash truncado não corresponderia.

    
por 09.01.2018 / 15:44
0

Eu não usaria um regex aqui, apenas uma comparação de strings:

md5 ()  { 
    sum=$(md5sum "$1" | awk '{print $1}')
    [[ $sum = "$2" ]] && echo fine || echo baarr; 
}
    
por 09.01.2018 / 19:21