Z ciekawości, porównując zmienną bash (jej wartość jest an integer
), można przetestować ją na pewnej predefiniowanej wartości zadeklarowanej jako int
lub string
.
Przykładowy skrypt :
#!/bin/bash
f1()
{
[ "$1" == "1" ] && echo "$FUNCNAME: \"1\" compared as string"
}
f2()
{
[[ "$1" -eq 1 ]] && echo "$FUNCNAME: \"1\" compared as int"
}
f1 $1
f2 $1
Wyjście :
$ ./param.sh 1
f1: "1" compared as string
f2: "1" compared as int
i
$ ./param.sh blah
$
Obie funkcje zachowują się w ten sam sposób, więc zastanawiam się, czy istnieje preferowany sposób sprawdzania zmiennej całkowitej? Wybrałbym sprawdzanie int
kontra int
bardziej rygorystyczne, ale zastanawiam się, czy robią to jakieś wady string
?
W tym przypadku f2()
jest również bardziej rygorystyczny w porównaniu, tzn. Przekazanie wartości dziesiętnej spowoduje jej uszkodzenie f1()
, ale nie spowoduje problemu.
Odpowiedzi:
Tak, wiele różnic. Na przykład
=
sprawdza dokładność równości łańcucha, ale-eq
ocenia arytmetycznie oba wyrażenia przed sprawdzeniem równości:Ponadto pusty ciąg znaków jest liczbowo równy zero:
Zupełnie inna klasa różnic pojawia się, gdy weźmiesz operatory porównania - biorąc pod uwagę
<
vs-lt
, na przykład:Wynika to z faktu, że ciąg „2” jest alfabetycznie po ciągu „10” (ponieważ 1 występuje przed 2), ale liczba „2” jest liczbowo mniejsza niż liczba „10”.
źródło
(( ... ))
operacje numeryczne.(( " 1 " == 1 )) && echo yes || echo no
wyniki wyes
Porównanie liczb całkowitych i ciągów staje się najbardziej znaczące, gdy porównujesz większe lub mniejsze niż:
Pierwszy nie powiedzie się, ponieważ 9 pojawia się po 11, gdy jest posortowane leksykograficznie.
Zauważ, że użycie cudzysłowów nie określa, czy porównujesz ciągi, czy liczby, operator tak. Możesz dodać lub usunąć powyższe cytaty, nie robi to żadnej różnicy. Bash przechwytuje niezdefiniowane zmienne w podwójnych nawiasach, więc cudzysłowy nie są konieczne. Używanie cudzysłowów z pojedynczymi nawiasami do testów numerycznych nie uratuje cię, ponieważ:
i tak jest błędem („wymagane wyrażenie całkowite”). Cytaty są skutecznym zabezpieczeniem przy porównywaniu ciągów w nawiasach pojedynczych:
Uwaga w podwójnych nawiasach, ale nie
""
będzie .-eq 0
== 0
źródło
[[
jest wystarczająco inteligentny, aby zapamiętać, gdzie są zmienne, i nie da się oszukać pustymi zmiennymi. Pojedyncze nawiasy kwadratowe ([
) nie mają tej funkcji i wymagają cudzysłowów.[[ -lt 11 ]]
jest błędem, alenothing=; [[ $nothing -lt 11 ]]
nie jest. Trochę przerobiłem ostatni akapit.Oprócz tego, co zostało powiedziane.
Porównywanie pod kątem równości jest szybsze z liczbami, chociaż w skryptach powłoki rzadko zdarza się potrzeba szybkich obliczeń.
źródło
=
, ponieważ użycie-eq
pasowałoby również do „+123”. Jeśli chcesz wiedzieć „Czy ta zmienna, gdy jest oceniana jako wyrażenie arytmetyczne, porównaj równe 123”, możesz tylko użyć-eq
. Jedyny raz widzę, gdzie programista nie dbałby o to, która definicja równości została zastosowana, kiedy wie, że zawartość zmiennej jest ograniczona do określonego wzorca wcześniej.b=234
) pasuje do tego wzorca - wiesz, że nie jest to +234 lub „234” lub „233 + 1”, ponieważ sam go przypisałeś, więc wiesz, że porównywanie go jako łańcucha i liczby jest jednakowo ważne. Ale skrypt OP, ponieważ pobiera dane wejściowe jako argument wiersza poleceń, nie ma tego ograniczenia - rozważ nazwanie go jako./param.sh 0+1
lub./param.sh " 1"