Comparaison de deux chaînes dans Bash

22

J'ai le ifbloc suivant dans mon script bash:

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

L'exécution du script n'entre pas dans mon ifbloc même si elle $PACKAGENAMEest égale à kakadu-v6_4-00902C. Qu'est-ce que je fais mal?

DemiSheep
la source
9
-eqest vrai pour les entiers, vous voulez tester une chaîne ou une expression régulière ( ==ou =~): mywiki.wooledge.org/BashGuide/TestsAndConditionals
jasonwryan
Merci, jasonwryanje vais jeter un œil à cette ressource!
DemiSheep

Réponses:

31

-eq est un opérateur arithmétique qui compare deux nombres.

Utilisez =(portable / standard sh) =~ou à la ==place.

Utilisez également des guillemets, car s'il ${PACKAGENAME}contient un espace ou un caractère générique, il sera divisé en plusieurs arguments, ce qui permet de [voir plus d'arguments que souhaité. Voir ici une liste des pièges bash courants.

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

Voir man bash, rechercher ( /) pour CONDITIONAL EXPRESSIONS.

polym
la source
1
Ah! Merci! Ça a marché! Je suis évidemment une recrue dans ce domaine. Je vous remercie pour votre aide!
DemiSheep
2
Avez-vous jeté un œil à tldp.org/LDP/Bash-Beginners-Guide/html ? C'est un très bon guide bash et vous aidera avec des exemples et des examens :).
polym
1
Merci polymje vais jeter un oeil, merci pour la ressource! Je vais ouvrir cet onglet à côté de mon guide VI. :)
DemiSheep
4
Entre crochets doubles, aucun fractionnement de mot n'est effectué, tout [[ $PACKAGENAME == "kakadu..." ]]comme OK.
glenn jackman
4
@glennjackman Attention cependant, même entre crochets, vous avez besoin de guillemets doubles autour des extensions de variables sur le côté droit de =, ==et !=, parce que ce côté est un motif, pas une chaîne. Par exemple, foo='*'; [[ whatever = $foo ]]c'est vrai.
Gilles 'SO- arrête d'être méchant'
6

Remplacez -eqpar == pour que votre bloc if soit le suivant: -

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

        echo "successfully entered if block!!"

fi
débutant
la source
5
N'oubliez pas de citer! Jetez un œil ici, pourquoi: mywiki.wooledge.org/BashPitfalls#A.5B_.24foo_.3D_.22bar.22_.5D
polym
@polym hey merci, mais je viens de donner la version minimaliste qui fonctionnait;): D.
débutant le
4

Une autre façon est de les nier:

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

Le bloc ci-dessus teste d'abord if "$PACKAGENAME"a une valeur quelconque, et sinon il se termine avec erreur et fait écho ?'this'}à stderr. Si son shell parent existe toujours, le test est réussi et il teste ensuite si la suppression de votre chaîne 'kakadu ...' de la variable entraîne une -zchaîne vide. Si ce n'est pas le cas, il émet à nouveau une erreur et quitte le shell. Si votre shell existe toujours à ce stade après l'exécution du bloc, sinon ce n'est pas le cas.

Ce genre de chose est probablement mieux implémenté dans une fonction. Comme:

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
)

Avec cette fonction, vous pouvez fournir autant d'arguments que votre système le permet. Si vous fournissez moins de 2, il retournera 1 et émettra un message à stderr. Si vous fournissez 2 arguments ou plus, il traitera tous comme des chaînes et renverra 0 si tous sont identiques et non nuls sinon il renverra le numéro d'argument qui échoue en premier la vérification.

Dans votre cas, il peut être utilisé comme:

{   
    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

Pour démontrer davantage, j'écrirai une autre fonction:

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
}

DÉMO:

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

SORTIE:

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
la source