Vergleichen von zwei Zeichenfolgen in Bash


22

Ich habe den folgenden ifBlock in meinem Bash-Skript:

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

Die Skriptausführung betritt meinen ifBlock nicht, obwohl $PACKAGENAMEgleich ist kakadu-v6_4-00902C. Was mache ich falsch?


9
-eqgilt für ganze Zahlen, Sie möchten auf eine Zeichenfolge oder einen regulären===~
Ausdruck

Danke, jasonwryanich schaue mir diese Ressource an!
DemiSheep

Antworten:


31

-eq ist ein arithmetischer Operator, der zwei Zahlen vergleicht.

Verwenden Sie =(tragbar / Standard sh) =~oder ==stattdessen.

Verwenden Sie auch Anführungszeichen, denn wenn ${PACKAGENAME}ein Leerzeichen oder ein Platzhalterzeichen enthalten ist, wird es in mehrere Argumente aufgeteilt, wodurch [mehr Argumente als gewünscht angezeigt werden. Sehen Sie sich hier eine Liste der gängigen Fallstricke an.

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

Siehe man bashsearch ( /) für CONDITIONAL EXPRESSIONS.


1
Ah! Vielen Dank! Es funktionierte! Ich bin offensichtlich ein Anfänger. Ich bin dankbar für Ihre Hilfe!
DemiSheep

2
Haben Sie sich tldp.org/LDP/Bash-Beginners-Guide/html angesehen ? Es ist eine sehr nette Bash-Anleitung und hilft Ihnen mit Beispielen und Prüfungen :).
Polym

1
Danke, polymich schau mal rein, danke für die Ressource! Ich öffne diesen Tab neben meiner VI-Anleitung. :)
DemiSheep

4
In doppelten Klammern erfolgt keine Worttrennung, also [[ $PACKAGENAME == "kakadu..." ]]ist es in Ordnung.
Glenn Jackman

4
jedoch , dass auch in doppelte Klammern @glennjackman Vorsicht, müssen Sie doppelte Anführungszeichen um variable Erweiterungen auf der rechten Seite =, ==und !=, weil die Seite ein Muster ist, kein String. Zum Beispiel foo='*'; [[ whatever = $foo ]]ist wahr.
Gilles 'SO- hör auf böse zu sein'


4

Ein anderer Weg ist, sie zu negieren:

: ${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

Der obige Block testet zuerst, ob "$PACKAGENAME"überhaupt ein Wert vorhanden ist, und wenn nicht, wird er mit einem Fehler beendet und gibt ein Echo ?'this'}von aus stderr. Wenn die übergeordnete Shell noch vorhanden ist, ist der Test bestanden. Anschließend wird geprüft, ob das Entfernen der Zeichenfolge 'kakadu ...' aus der Variablen zu einer -zleeren Zeichenfolge führt. Wenn dies nicht der Fall ist, wird erneut ein Fehler ausgegeben und die Shell verlassen. Wenn Ihre Shell zu diesem Zeitpunkt noch vorhanden ist, nachdem der Block ausgeführt wurde, ist dies ansonsten nicht der Fall.

Wahrscheinlich lässt sich so etwas am besten in eine Funktion implementieren. Mögen:

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
)

Mit dieser Funktion können Sie so viele Argumente angeben, wie Ihr System zulässt. Wenn Sie weniger als 2 angeben, wird 1 zurückgegeben und eine Nachricht an gesendet stderr. Wenn Sie 2 oder mehr Argumente angeben, werden alle als Zeichenfolgen behandelt, und es wird 0 zurückgegeben, wenn alle identisch und nicht null sind. Andernfalls wird die Argumentnummer zurückgegeben, bei der die Prüfung zuerst fehlschlägt.

In Ihrem Fall kann es wie folgt verwendet werden:

{   
    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

Zur weiteren Demonstration schreibe ich eine andere Funktion:

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
}

DEMO:

{  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
}  

AUSGABE:

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.