Bash: Ich habe [[<]] gebrochen

14

Ich schrieb ein Bash-Skript und plötzlich begann dieses Verhalten:

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

-ltfunktioniert aber einwandfrei:

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

habe ich versehentlich <irgendwie überschrieben ?

Hier ist ein Skript, das ich geschrieben habe, um dieses Verhalten zu testen:

#!/bin/bash

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

    echo
done

Hier ist die Ausgabe:

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

Wenn Sie im Skript auf wechseln <, erhalten Sie -lteine normale Ausgabe ( 5 10wird beispielsweise angezeigt).

Der Neustart hat nichts geändert.

Meine Bash-Version ist GNU Bash, Version 4.3.42 (1) -Release (x86_64-pc-linux-gnu). Ich bin auf Ubuntu 15.10. Ich weiß nicht, welche anderen Informationen hier relevant sind.

Schnecke-auf-einer-Suche
quelle
16
Mit der <Operation führen Sie einen Zeichenfolgenvergleich durch, während der -ltOperator ein numerischer Vergleich ist. Wenn Sie sich die aufgelisteten Ergebnisse ansehen, werden Sie es merken. Numerisch 2 ist kleiner als 10, alphabetisch umgekehrt.
MelBurslan

Antworten:

51

Von der bashManpage.

Bei Verwendung mit [[sortieren die Operatoren <und> lexikografisch nach dem aktuellen Gebietsschema.

In der Ausgabe scheint es wie geplant zu funktionieren.

Steve
quelle
35
Lesen Sie mit anderen Worten die Manpage, bevor Sie davon ausgehen, dass Sie einen Fehler gefunden haben. ;)
Wildcard
Wahr. Vielleicht hat das Skript, an dem ich ursprünglich gearbeitet habe, tatsächlich "richtig" funktioniert (wie beim Fehlschlagen von [[$ myvar <13]]), als ich dieses Verhalten bemerkte. Was sollte ich jetzt mit dieser Frage tun? Ändern wir auf dieser Site den Titel, um [gelöst] oder etwas aufzunehmen? Sollte der Titel trotzdem in einen aussagekräftigeren geändert werden?
Snail-on-a-Quest
2
Nein, ändern Sie nicht den Titel der Frage. Das Häkchen neben dieser Antwort reicht aus, um anzuzeigen, dass die Frage gelöst wurde.
saiarcot895
14
@Wildcard Das OP geht nicht davon aus, dass es einen Fehler gefunden hat. Sie schlagen ausdrücklich vor, dass sie vielleicht etwas getan haben, um das Verhalten zu ändern. Sogar der Titel nimmt so viel an!
jpmc26
5

Wie wäre es mit:

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

Laut http://www.tldp.org/LDP/abs/html/dblparens.html

Ähnlich wie der Befehl let erlaubt das Konstrukt ((...)) eine arithmetische Erweiterung und Auswertung. In seiner einfachsten Form würde a = $ ((5 + 3)) a auf 5 + 3 oder 8 setzen. Dieses Konstrukt in doppelten Klammern ist jedoch auch ein Mechanismus, um beispielsweise die Manipulation von Variablen in Bash im C-Stil zu ermöglichen , ((var ++)).

PaulSmecker
quelle
2
Sie verpassen den Punkt der Frage - es geht nicht darum, wie ich diese Werte vergleichen kann. aber "warum verhält es sich so wie es ist?"
guntbert
7
Dies wurde bereits beantwortet. Da er jedoch einen arithmetischen Ausdruck verwenden wollte, sollte darauf hingewiesen werden, dass es Konstrukte gibt, mit denen Sie diese in der Shell verwenden können.
PaulSmecker
3

Erstens [[ ist nicht POSIX und sollte vermieden werden.

Zweitens, wenn Sie <als Teil eines arithmetischen Tests verwenden möchten, können Sie dies tun, jedoch mit einer anderen Syntax:

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

Oder:

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