Porównywanie dwóch ciągów w Bash

22

Mam następujący ifblok w skrypcie bash:

if [ ${PACKAGENAME} -eq kakadu-v6_4-00902C ]; then
  echo "successfully entered if block!!"
fi

Wykonanie skryptu nie wchodzi do mojego ifbloku, mimo że $PACKAGENAMEjest równe kakadu-v6_4-00902C. Co ja robię źle?

DemiSheep
źródło
9
-eqjest prawdziwe w przypadku liczb całkowitych, chcesz przetestować ciąg lub wyrażenie regularne ( ==lub =~): mywiki.wooledge.org/BashGuide/TestsAndConditionals
jasonwryan
Dzięki jasonwryanPrzyjrzę się temu zasobowi!
DemiSheep

Odpowiedzi:

31

-eq jest operatorem arytmetycznym, który porównuje dwie liczby.

Użyj =(przenośny / standardowy sh) =~lub ==zamiast niego.

Używaj także cudzysłowów, ponieważ jeśli ${PACKAGENAME}zawiera biały znak lub znak wieloznaczny, zostanie on podzielony na wiele argumentów, co spowoduje [wyświetlenie większej liczby argumentów niż jest to pożądane. Zobacz tutaj listę typowych pułapek bash.

if [ "${PACKAGENAME}" = 'kakadu-v6_4-00902C' ]; then
    echo "successfully entered if block!!"
fi

Zobacz man bash, szukaj ( /) dla CONDITIONAL EXPRESSIONS.

polim
źródło
1
Ach! Dziękuję Ci! Zadziałało! Jestem oczywiście debiutantem. Jestem wdzięczny za twoją pomoc!
DemiSheep
2
Czy oglądałeś tldp.org/LDP/Bash-Beginners-Guide/html ? To bardzo fajny przewodnik bashowy, który pomoże Ci w przykładach i egzaminach :).
polym
1
Dzięki polym, spojrzę, dzięki za zasób! Otworzę tę kartę obok mojego przewodnika VI. :)
DemiSheep
4
W podwójnych nawiasach nie ma podziału słów, więc [[ $PACKAGENAME == "kakadu..." ]]jest OK.
glenn jackman
4
@glennjackman Uważaj jednak, że nawet w podwójnych nawiasach potrzebujesz podwójnych cudzysłowów wokół zmiennych rozwinięć po prawej stronie =, ==a !=ponieważ ta strona jest wzorem, a nie łańcuchem. Na przykład foo='*'; [[ whatever = $foo ]]prawda.
Gilles 'SO - przestań być zły'
6

Wymień -eqsię == więc jeśli blok będzie to: -

if [ ${PACKAGENAME} == kakadu-v6_4-00902C ]; then

        echo "successfully entered if block!!"

fi
początkujący
źródło
5
Nie zapomnij zacytować! Rzucić okiem tutaj, dlaczego: mywiki.wooledge.org/BashPitfalls#A.5B_.24foo_.3D_.22bar.22_.5D
Polym
@polym hej dzięki, ale właśnie dałem minimalistyczną wersję, która działała;): D.
początkujący
4

Innym sposobem jest ich zanegowanie:

: ${PACKAGENAME:?'$PACKAGENAME variable is empty!'} #emits error and exits
[ -z "${PACKAGENAME#kakadu-v6_4-00902C}" ] || { #if var - str not empty do block
    echo '$PACKAGENAME is not kakadu-v6_4-00902C' 
    exit 1
} >&2

Wyżej blokowe Pierwsze testy jeśli "$PACKAGENAME"ma żadnej wartości w ogóle, a jeśli nie to wyjście z błędem i echa ?'this'}do stderr. Jeśli jego powłoka nadrzędna nadal istnieje, test przeszedł pomyślnie, a następnie sprawdza, czy usunięcie łańcucha „kakadu ...” ze zmiennej skutkuje -zpustym ciągiem. Jeśli nie, to ponownie emituje błąd i wychodzi z powłoki. Jeśli twoja powłoka nadal istnieje w tym momencie coś po wykonaniu bloku, w przeciwnym razie tak nie jest.

Prawdopodobnie najlepiej jest zaimplementować tę funkcję w funkcji. Lubić:

argeq() ( i= : ${2?^MERR: not enough parameters!} #$#>=2 || quit w/ err ^M == \r
    z() { return $((${#1}>0)) ; } #return 1 if ${#1}>0 else 0
    until z "${2+?}" $((i=i+1)) #until $2 is not set...
    do  ! z "$1" && z "${1#"$2"}" || #$1 != '' && $1 - $2 == '' or...
        exit $((i${1:++1})) #exit $? == failed arg count
    shift ; done #shift away one param ; continue loop
)

Dzięki tej funkcji możesz podać tyle argumentów, ile pozwoli twój system. Jeśli podasz mniej niż 2, zwróci 1 i wyśle ​​wiadomość do stderr. Jeśli podasz 2 lub więcej argumentów, potraktuje wszystkie jako łańcuchy i zwróci 0, jeśli wszystkie są identyczne i nie będą zerowe, w przeciwnym razie zwróci numer argumentu, który jako pierwszy nie przejdzie kontroli.

W twoim przypadku można go użyć w następujący sposób:

{   
    PACKAGENAME='kakadu-v6_4-00902C'
    argeq "$PACKAGENAME" kakadu-v6_4-00902C &&
        echo "kakadu-v6_4-00902C == $PACKAGENAME" ||
        echo failure
    ! argeq "${PACKAGENAME#*-}" kakadu-v6_4-00902C &&
        echo "kakadu-v6_4-00902C != ${PACKAGENAME#*-}" ||
        echo failure
}

###OUTPUT###
kakadu-v6_4-00902C == kakadu-v6_4-00902C
kakadu-v6_4-00902C != v6_4-00902C

Aby zademonstrować dalej, napiszę inną funkcję:

aeqecho() { i=$((i+1)) #inc for line#
    argeq "$@" && echo "$i : yay" || #allswell or
    ! e=$? ${2+:} return || #save $?; ! exclusive || to drop ERRs
    echo "$i : shite - arg$e failed" #report failure
}

PRÓBNY:

{  i= s=string
   aeqecho $s #1
   aeqecho $s $s #2
   aeqecho "$s $s" #3
   aeqecho "$s $s" "${s} string" #4
   aeqecho "${s}1" $s string #5
   aeqecho "" "" "" #6
   aeqecho "" "$s" $s #7
   aeqecho 1 "${s#$s}1" $((2-1)) #8                     
   aeqecho $s $s $s $s $s $s $s $s $s $s $s $s stng #9  
   aeqecho $s $s $s $s $s $s $s $s $s $s $s $s string #10
}  

WYDAJNOŚĆ:

ERR: not enough parameters!
2 : yay
ERR: not enough parameters!
4 : yay
5 : shite - arg2 failed
6 : shite - arg1 failed
7 : shite - arg1 failed
8 : yay
9 : shite - arg13 failed
10 : yay
mikeserv
źródło