festança: eu quebrei [[<]]

14

Eu estava escrevendo um script bash e de repente esse comportamento começou:

[[ 1 < 2 ]]; echo $?  # outputs 0
[[ 2 < 13 ]]; echo $? # outputs 1

mas -ltfunciona perfeitamente:

[[ 1 -lt 2 ]]; echo $?  # outputs 0
[[ 2 -lt 13 ]]; echo $? # outputs 0

substituí acidentalmente de <alguma forma?

Aqui está um script que escrevi para testar esse comportamento:

#!/bin/bash

for a in {1..5}
do
    for b in {1..20}
    do
        [[ $a < $b ]] && echo $a $b
    done

    echo
done

aqui está a saída:

1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
1 11
1 12
1 13
1 14
1 15
1 16
1 17
1 18
1 19
1 20

2 3
2 4
2 5
2 6
2 7
2 8
2 9
2 20

3 4
3 5
3 6
3 7
3 8
3 9

4 5
4 6
4 7
4 8
4 9

5 6
5 7
5 8
5 9

mudar <para -ltno script fornece saída normal ( 5 10aparece por exemplo).

A reinicialização não mudou nada.

Minha versão do bash é o GNU bash, versão 4.3.42 (1) -release (x86_64-pc-linux-gnu). Estou no Ubuntu 15.10. Não sei que outras informações são relevantes aqui.

caracol em uma busca
fonte
16
com a <operação, você está fazendo uma comparação de cadeias, enquanto o -ltoperador é uma comparação numérica. Se você observar os resultados listados, perceberá isso. Numericamente 2 é menor que 10, alfabeticamente, ao contrário.
MelBurslan

Respostas:

51

Na bashpágina do manual.

Quando usados ​​com [[, os operadores <e> classificam lexicograficamente usando o locale atual.

A partir da saída, parece estar funcionando como projetado.

Steve
fonte
35
Em outras palavras, leia a página de manual antes de assumir que encontrou um erro. ;)
Curinga
Verdade. Talvez o script em que eu estava trabalhando originalmente tenha começado a funcionar 'corretamente' (como na falha de [[$ myvar <13]]) quando percebi esse comportamento. Há algo que eu deva fazer com esta pergunta agora? Neste site, alteramos o título para incluir [resolvido] ou algo assim? O título deve ser alterado de qualquer maneira para algo mais descritivo?
caracol em questão
2
Não, não mude o título da pergunta. A marca de seleção ao lado desta resposta é suficiente para indicar que a pergunta foi resolvida.
Saiarcot895
14
@Wildcard O OP não assume que encontrou um bug. Eles sugerem explicitamente que talvez tenham feito algo para alterar o comportamento. Até o título assume o mesmo!
Jpmc26
5

E se:

for a in {1..5}; 
do     
  for b in {1..20};     
  do         
    (( $a < $b )) && echo $a $b
  done      
  echo
done

De acordo com http://www.tldp.org/LDP/abs/html/dblparens.html

Semelhante ao comando let, o construto ((...)) permite expansão e avaliação aritmética. Na sua forma mais simples, a = $ ((5 + 3)) definiria 5 como 3 + ou 8. No entanto, essa construção de parênteses duplos também é um mecanismo para permitir a manipulação de variáveis ​​no estilo C no Bash, por exemplo , ((var ++)).

PaulSmecker
fonte
2
Você está perdendo o objetivo da pergunta - não é "como posso comparar esses valores?" mas "por que se comporta dessa maneira?".
Guntbert 31/05
7
Isso já foi respondido. Mas como ele queria usar uma expressão aritmética, pode valer a pena ressaltar que existem construções que permitem que você as use no shell.
PaulSmecker
3

Em primeiro lugar, [[ não é POSIX e deve ser evitado.

Em segundo lugar, se você deseja usar <como parte de um teste aritmético, pode fazer isso, mas com sintaxe diferente:

if [ $((2 < 13)) = 1 ]
then
  echo '2 is less than 13'
else
  echo '2 is greater or equal to 13'
fi

Ou:

if expr 2 '<' 13
then
  echo '2 is less than 13'
else
  echo '2 is greater or equal to 13'
fi
Steven Penny
fonte