Porównaj liczby całkowite w bash, oczekiwano jednoargumentowego operatora

137

Poniższy kod daje

[: -ge: oczekiwano jednoargumentowego operatora

kiedy

i=0

if [ $i -ge 2 ]
then
    #some code
fi

czemu?

Filip Ekberg
źródło

Odpowiedzi:

295

Twój problem wynika z faktu, że $ima wartość pustą, gdy wyciąg nie powiedzie się. Zawsze cytuj swoje zmienne podczas wykonywania porównań, jeśli istnieje najmniejsza szansa, że ​​jedna z nich może być pusta, np .:

if [ "$i" -ge 2 ] ; then
  ...
fi

Dzieje się tak z powodu sposobu, w jaki powłoka traktuje zmienne. Przyjmijmy oryginalny przykład,

if [ $i -ge 2 ] ; then ...

Pierwszą rzeczą, jaką wykonuje powłoka podczas wykonywania tej konkretnej linii kodu, jest podstawienie wartości $i, tak jak zrobiłaby to funkcja wyszukiwania i zamiany w Twoim ulubionym edytorze . Więc załóżmy, że $ito jest puste lub, jeszcze bardziej obrazowe, załóżmy, że $ijest to kilka spacji! Powłoka zastąpi $iw następujący sposób:

if [     -ge 2 ] ; then ...

Teraz, zmienne podstawienia są wykonywane, wpływy powłoki z porównania i .... nie dlatego, że nie widzę nic zrozumiałego dla lewej z -gt. Jednak cytując $i:

if [ "$i" -ge 2 ] ; then ...

staje się:

if [ "    " -ge 2 ] ; then ...

Powłoka widzi teraz podwójne cudzysłowy i wie, że faktycznie porównujesz cztery spacje z 2 i pominie if.

Masz również możliwość określenia domyślnej wartości, $ijeśli $ijest pusta, w następujący sposób:

if [ "${i:-0}" -ge 2 ] ; then ...

Będzie to zastąpić wartość 0 zamiast $ijest $inieokreślona. Nadal utrzymuję cudzysłowy, ponieważ znowu, jeśli $ijest to kilka pustych znaków, to nie liczy się jako niezdefiniowane , nie zostanie zastąpione przez 0 i ponownie napotkasz problem.

Przeczytaj to, kiedy będziesz mieć czas. Powłoka jest przez wielu traktowana jak czarna skrzynka, ale działa na bardzo niewielu i bardzo prostych zasadach - kiedy już wiesz, jakie są te reguły (jedną z nich jest sposób działania zmiennych w powłoce, jak wyjaśniono powyżej), powłoka będzie nie mam już dla ciebie tajemnic.

vladr
źródło
7
cytowanie zmiennej spowoduje nowy błąd, taki jak oczekiwano wyrażenia całkowitego
Néstor
@ Néstor źle , cytowanie zmiennej NIE spowoduje nowego błędu, takiego jak oczekiwane wyrażenie całkowite, jeśli zmienna jest numeryczna; podanie nienumerycznej wartości zmiennej, czy to w cudzysłowie czy nie, spowoduje wspomniany błąd.
vladr
6

Sądząc po komunikacie o błędzie, wartość i była pustym ciągiem podczas jego wykonywania, a nie 0.

starblue
źródło
6

Muszę dodać moje 5 centów. Widzę, że wszyscy używają [lub [[, ale warto wspomnieć, że nie są one częścią składni if.

W przypadku porównań arytmetycznych użyj ((...))zamiast tego.

((...)) jest poleceniem arytmetycznym, które zwraca kod zakończenia równy 0, jeśli wyrażenie jest różne od zera, lub 1, jeśli wyrażenie ma wartość zero. Używany również jako synonim „let”, jeśli potrzebne są efekty uboczne (przypisania).

Zobacz: ArithmeticExpression

Roman Newaza
źródło
2

Twój fragment scenariusza działa po prostu świetnie. Czy na pewno nie przypisujesz niczego innego przed if do „i”?

Częstym błędem jest również niepozostawianie spacji po i przed nawiasami kwadratowymi.

Fernando Miguélez
źródło