Por que os testes bash são tão exigentes quanto a espaço em branco?

5

Como um programador basicamente Java, acho a construção bash if - then bastante confusa, especialmente em relação ao espaço em branco. Alguém pode explicar por que o primeiro funciona, mas não o segundo ou terceiro?

#works
if [ -n $1 ]; then echo "parameterized"; fi

#output: ./links: Zeile 1: [-n: Kommando nicht gefunden.
if [-n $1 ]; then echo "parameterized"; fi

#output: ./links: Zeile 1: [: Fehlende ']'
if [ -n $1]; then echo "parameterized"; fi
    
por Konrad Höffner 28.02.2014 / 12:22

2 respostas

10

A inconsistência é em grande parte devido a razões históricas.

O uso de parênteses como o comando condicional veio após o uso de parênteses em padrões curinga. Então, no momento em que [ -n foo ] entrou em cena, [foo] já significava "um arquivo cujo nome é f ou o ". Enquanto poucos usos do operador de braquetes na prática teriam conflitado com usos realistas dos braquetes em curingas, os autores escolheram não arriscar quebrar scripts existentes alterando a sintaxe. Essa escolha de design também facilitou a implementação: inicialmente [ foi implementado como um comando externo, o que não poderia ter sido feito se o espaço após [ tivesse sido opcional. (Os sistemas modernos ainda têm [ como um comando externo, mas quase todos os shells modernos também o fazem.)

Por motivos semelhantes, o seu código de "trabalho" está incorreto na maioria das circunstâncias. $1 não significa “o valor do parâmetro 1”: significa “pegar o valor do parâmetro 1, dividi-lo em palavras separadas no espaço em branco (ou qualquer que seja o valor de IFS ) e interpretar cada palavra como glob padronizar". A maneira de escrever “o valor do parâmetro 1” requer aspas duplas: "$1" . Consulte Quando é necessário fazer uma cotação dupla? para o assunto gritty. Você não precisa entender isso; tudo que você precisa lembrar é: sempre coloca aspas duplas em torno das substituições de variável "$foo" e substituições de comando "$(foo)" . Assim:

if [ -n "$1" ]; then …

No bash, ksh e zsh, mas não no sh simples, você também pode usar colchetes duplos. Parênteses únicos [ … ] são analisados como um comando comum (e, de fato, [ é um comando comum, embora geralmente embutido). Os colchetes duplos são uma construção sintática separada e você pode omitir as aspas duplas na maioria das vezes.

if [[ -n $1 ]]; then …

No entanto, há uma exceção: [[ "$foo" = "$bar" ]] para testar se as duas variáveis têm o mesmo valor requer aspas duplas em torno de $bar , caso contrário, $bar é interpretado como um padrão de caractere curinga. Novamente, em vez de lembrar os detalhes, você deve usar aspas duplas o tempo todo.

    
por 03.03.2014 / 03:53
8

na verdade, o caractere [ é um comando de shell interno que avalia o argumento até o argumento ]
bash use argumento separado por espaço, por isso, se você quiser chamar [ , você precisa colocar um espaço ou ele tentará executar o comando [-n , que não é uma função ou binário, saiba (pelo menos até você criar um) .

Quando você escreve [-n $1 ] , significa [-n com os argumentos $1 e ] , o que não faz sentido | e se você colocar [ -n $1] , significa [ com o argumento -n e $1] , mas faltando o argumento ] da sua função [ para que não seja possível avaliar sua expressão

    
por 28.02.2014 / 12:30