Comparação de strings no bash. [[: não encontrado

165

Estou tentando comparar seqüências de caracteres no bash. Eu já encontrei uma resposta sobre como fazê-lo no stackoverflow . No script que estou tentando, estou usando o código enviado por Adam na pergunta mencionada:

#!/bin/bash
string='My string';

if [[ "$string" == *My* ]]
then
  echo "It's there!";
fi

needle='y s'
if [[ "$string" == *"$needle"* ]]; then
  echo "haystack '$string' contains needle '$needle'"
fi

Eu também tentei abordagem do ubuntuforums que você pode encontrar no segundo post

if [[ $var =~ regexp ]]; then
  #do something
fi

Nos dois casos, recebo erro:

[[: not found

O que estou fazendo de errado?

user1581900
fonte
Eu posso fazer errado, mas usar um único colchete sempre funcionou para mim.
Markus Unterwaditzer 01/09/12
1
O que /bin/bash --versionimprime?
themel
4
[não funcionará neste caso, porque não suporta padrões.
Ansgar Wiechers

Respostas:

157

[[é um bash-builtin. Sua /bin/bashnão parece ser uma festa real.

De um comentário:

Adicionar #!/bin/bashna parte superior do arquivo

Ansgar Wiechers
fonte
se eu digitar: type '[[' i get [[é uma palavra
user1581900 01/09/12
5
Você obtém o mesmo resultado ao executar /bin/bash -c "type [["?
Ansgar Wiechers
43
Isto aconteceu-me porque eu esqueci de acrescentar #!/bin/bashna parte superior do meu arquivo
morphatic
12
Aconteceu comigo porque eu corri o script com shmuita frustração. Agora só preciso refazer tudo o que desfiz antes de encontrar esta resposta.
Louis Loudog Trottier
174

Como você está executando seu script? Se você fez com

$ sh myscript

Você deveria tentar:

$ bash myscript

ou, se o script for executável:

$ ./myscript

sh e bash são duas conchas diferentes . Enquanto no primeiro caso você está passando seu script como argumento para o intérprete sh, no segundo caso você decide na primeira linha qual intérprete será usado.

Akos K
fonte
eu tenho permissão negada dessa maneira. com sudo ./myscript, seu comando não foi encontrado
user1581900
11
não chmod + x myscript , em seguida, executar novamente, você não precisa de sudo
Akos K
2
Como você está invocando seu script?
Akos K
como você disse. Normalmente eu chamo isso com '$ sh myscipt.sh'. 2 ª vez depois de fazer chmod + x myscript.sh i chamou-lhe com ./myscript.sh
user1581900
5
O erro é esperado quando você executa o script via sh myscript.sh, porque /bin/shemula um shell Bourne onde [[não está embutido. No entanto, a execução do script via ./script.shnão deve gerar um erro, pois nesse caso o shebang deve causar o /bin/bashuso.
Ansgar Wiechers
81

É a primeira linha do seu script:

#!/bin/bash

ou

#!/bin/sh

o sh shell produz essas mensagens de erro, não o bash

Wiley
fonte
1
A primeira linha também estava faltando para mim, produzindo o erro mencionado pelo autor!
Anónimo
14

Eu tive esse problema ao instalar o Heroku Toolbelt

Foi assim que resolvi o problema

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 ago 15  2012 /bin/sh -> dash

Como você pode ver, / bin / sh é um link para "dash" (não bash), e [[é uma sacralidade sintática. Acabei de substituir o link para / bin / bash. Cuidado usando rm como este em seu sistema!

$ sudo rm /bin/sh
$ sudo ln -s /bin/bash /bin/sh
jperelli
fonte
6
Substituir o padrão shda sua distribuição é IMHO mal recomendado. Um shell que é executado com shdeve trabalhar com dash; caso contrário, isso é um bug no script. Se você precisar de bashrecursos, use bash, não sh.
Tripleee
4
isso soa terrível tbh
MrVaykadji
2
Concordo, foi apenas uma solução feia. Uma solução semelhante, porém melhor, seria usar update-alternatives(no debian-linux) como este justinconover.wordpress.com/2012/05/14/… mas no final, seria o mesmo.
jperelli
13

Como @Ansgar mencionou, [[é um basismo, ou seja, embutido no Bash e não disponível para outras conchas. Se você deseja que seu script seja portátil, use [. As comparações também precisarão de uma sintaxe diferente: altere ==para =.

Amedee Van Gasse
fonte
Verifiquei um pouco com o Ubuntu 16.04 e (sh ->) dash 0.5.8-2.1ubuntu2 e constatei que [funciona bem em combinação com "-eq" e similares. Informações semelhantes sobre operadores de comparação para este contexto podem ser encontradas aqui: stackoverflow.com/questions/10849297/… - Eu também falei com o operador de avaliação (()) conforme recomendado no próximo link, mas que pareceu falhar nas minhas alterações invasivas mínimas / ou / precisaria de um nível muito mais profundo de alterações de código. softpanorama.org/Scripting/Shellorama/Control_structures/…
Alexander Stohr
3

Especifique bash em vez de sh ao executar o script. Pessoalmente, notei que eles são diferentes no ubuntu 12.10:

bash script.sh arg0 ... argn

Smeterlink
fonte
Isso corrigiu para mim!
21815 Djamillah