Usando um caractere curinga em uma condição para corresponder ao início de uma string

2

Tentando que uma variável atenda a uma string de texto que varia por tamanho. A parte da string que importa é o primeiro par de caracteres.

var1=hello  
if [ $var1 == hello ]; then  
    echo success  
fi

Ou

var1=hello  
if [ $var1 == h*o ]; then  
    echo success  
fi

Saídas: sucesso

Mas como eu me preocupo com os 3 primeiros caracteres, isso parece lógico, mas não funciona:

var1=hello  
if [ $var1 == hel* ]; then  
    echo success  
fi

Saídas: -bash: [: muitos argumentos

Como eu só me preocupo com os primeiros dois personagens, posso fazer isso:

var1=hello 
if [ ${var1:0:3} == hel ]; then 
    echo success  
fi

Isso funcionaria, mas estou procurando uma explicação do motivo pelo qual estou obtendo esse erro e uma possível melhor solução por escrito.

    
por EAG08 22.03.2016 / 23:08

4 respostas

3

Quando você usa * em if , ele faz a expansão do nome do arquivo. Portanto, na primeira instância, h*o provavelmente corresponde a um arquivo em seu diretório atual e, portanto, o teste foi aprovado.

O hel* corresponde a vários arquivos e, portanto, se tornou muitos argumentos para o comando if .

Tente usar if [[ $var1 == hel* ]]; then

Os colchetes duplos transformam o teste em um regex e o curinga * funcionará conforme o esperado.

    
por 22.03.2016 / 23:17
1

Eu tenho um truque que eu uso para hackear regex sem usar o regex bash. Exemplo é para o nº 2. A maneira como isso funciona é que o grep não retorna nenhuma saída (portanto, uma string inexistente) se não corresponder a nada. Portanto, há dois testes, -z significa "string nula" e -n é "tem dados".

if [ -n "'echo $var1 | grep -e 'h.*o''" ] ; then
  echo 'water found'
fi
    
por 22.03.2016 / 23:26
1

[ * é um comando normal, semelhante a grep , find ou cat . Você deve conseguir encontrá-lo em /bin . Como é um programa separado, o shell executará seu conjunto normal de expansões antes de entregar [ de seus argumentos.

Como já foi mencionado, como você está usando * em seus testes, está obtendo expansões glob. Observe que, mesmo se você usar aspas, como 'hel*' , isso provavelmente não funcionará como esperado, porque [ não suporta padrões. No caso de h*o working, isso provavelmente se deve à presença de um arquivo chamado hello em seu diretório atual e nenhum outro arquivo que corresponda a esse padrão. Se funcionar sem um arquivo hello , você poderá ter uma implementação ímpar e provavelmente seu script falhará em outros sistemas.

Dependendo das suas necessidades, existem algumas opções. Bash, Zsh e alguns outros shells possuem o [[ embutido. Uma vez que é construído, pode dar um tratamento especial aos seus argumentos, incluindo evitar a expansão glob. Além disso, pode fazer correspondência de padrões. Experimente

var1=hello  
if [[ "$var1" = hel* ]]; then  
    echo success  
fi

Além disso, observe a falta de citações em torno do padrão. Sem as aspas, hel* é tratado como um padrão por [[ , com aspas (simples ou dupla), "hel*" é tratado literalmente.

Se você precisar de compatibilidade mais ampla, como shells sem [[ , você pode usar o grep:

var1=hello
if echo "$var1" | grep -qe 'hel.*' ; then
    echo success
fi

Não é necessário [ ou [[ aqui, mas as cotações em torno de 'hel.*' são.

* Alguns shells realmente têm [ embutido, mas isso é para fins de eficiência. Ele deve ainda se comportar de forma idêntica ao executável separado, incluindo ter seus argumentos sujeitos ao "mangling" normal do shell.

    
por 23.03.2016 / 18:10
0

Que tal isso?

if [["$ var1" == "hel" *]]

Forneça o caractere curinga fora das aspas ao fazer uma comparação de string.

    
por 22.08.2018 / 18:42