Por que não é [-n] falso como [-n “”]?

21

A minha pergunta é sobre os valores de retorno produzidos por este código:

if [ -n ]; then echo "true"; else echo "false"; fi

Isto imprime true .

Seu teste complementar usando [ -z ] também imprime true :

if [ -z ]; then echo "true"; else  echo "false"; fi

No código acima, por que o teste [ -n ] assume o valor da string que não é passado, pois não é nulo?

O código abaixo imprime false . Isso é esperado, pois o valor passado da string é nulo e tem comprimento zero.

if [ -n "" ]; then echo "true"; else  echo "false"; fi
    
por Ravi Kumar 27.10.2017 / 17:25

3 respostas

14

[ x ] é equivalente a [ -n x ] mesmo se x começar com - fornecido não há operandos.

$ [ -o ] ; echo $?
0
$ [ -eq ] ; echo $?
0
$ [ -n -o ] ; echo $?
0
$ [ -n -eq ] ; echo $?
0
    
por 27.10.2017 / 17:29
31

[ -n ] não usa o teste -n .

O -n em [ -n ] não é um teste. Quando há apenas um argumento entre [ e ] , esse argumento é uma sequência testada para ver se está vazia. Mesmo quando essa cadeia tiver um - inicial, ela ainda será interpretada como um operando, não como um teste. Como a string -n não está vazia, ela contém dois caracteres, - e n , não zero caracteres - [ -n ] é avaliado como verdadeiro.

Como Ignacio Vazquez-Abrams diz , onde string é um único argumento, o teste realizado em string em [ string ] é o mesmo que o teste realizado por [ -n string ] . Quando string é -n , nada de especial acontece. O -n em [ -n ] e o segundo -n em [ -n -n ] são simplesmente strings sendo testadas quanto ao vazio.

Quando há apenas um argumento entre [ e ] , esse argumento é sempre uma string a ser testada quanto à não necessidade, mesmo que seja o mesmo que um teste. Da mesma forma, quando há dois argumentos entre [ e ] e o primeiro deles é -n , o segundo é sempre uma sequência a ser testada quanto ao não-imprevisibilidade, mesmo que tenha o mesmo nome que um teste . Isso ocorre simplesmente porque a sintaxe para [ insiste em que um único argumento entre [ e ] ou depois de -n é um operando de cadeia de caracteres.

Pelo mesmo motivo que [ -n ] não usa o teste -n , [ -z ] não usa o teste -z .

Você pode aprender mais sobre [ in bash examinando a ajuda para isso. Observe que é um shell embutido :

$ type [
[ is a shell builtin

Assim, você pode executar help [ para obter ajuda:

$ help [
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal ']', to match the opening '['.

Para mais informações, incluindo quais testes são suportados e como eles funcionam, você terá que ver a ajuda em test . Quando você executar o comando help test , obterá uma lista detalhada. Em vez de reproduzir tudo, aqui está a parte sobre operadores de string:

      -z STRING      True if string is empty.

      -n STRING
         STRING      True if string is not empty.

      STRING1 = STRING2
                     True if the strings are equal.
      STRING1 != STRING2
                     True if the strings are not equal.
      STRING1 < STRING2
                     True if STRING1 sorts before STRING2 lexicographically.
      STRING1 > STRING2
                     True if STRING1 sorts after STRING2 lexicographically.

Observe que -n STRING e apenas STRING fazem a mesma coisa: eles testam se a string STRING não está vazia.

    
por 27.10.2017 / 17:46
12

[ -n ] é verdadeiro porque o comando [ (também conhecido como o comando test ) age sobre o número de argumentos que ele recebe. Se for dado apenas um único argumento, o resultado será "verdadeiro" se o argumento for uma string não vazia. "-n" é uma string com 2 caracteres, não vazia, portanto, "true".

    
por 27.10.2017 / 17:45

Tags