Comparando duas strings no Bash

22

Eu tenho o seguinte if block no meu script bash:

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

A execução do script não está entrando no bloco if , mesmo que $PACKAGENAME seja igual a kakadu-v6_4-00902C . O que estou fazendo errado?

    
por DemiSheep 17.07.2014 / 20:07

3 respostas

31

-eq é um operador aritmético, que compara dois números.

Use = (portátil / padrão sh ), =~ ou == .

Use também aspas, porque se ${PACKAGENAME} contiver um espaço em branco ou um caractere curinga, ele será dividido em vários argumentos, o que fará com que [ veja mais argumentos do que o desejado. Veja aqui uma lista de armadilhas comuns.

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

Veja man bash , pesquisa ( / ) para CONDITIONAL EXPRESSIONS .

    
por 17.07.2014 / 20:11
6

Substitua -eq por == para que seu bloco if seja o seguinte: -

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

        echo "successfully entered if block!!"

fi
    
por 17.07.2014 / 20:17
4

Outra maneira é negá-los:

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

O bloco acima testa primeiro se "$PACKAGENAME" tem algum valor e, se não sair com erro, ecoa ?'this'} para stderr . Se o shell pai ainda existir, o teste passou e, em seguida, ele testa se a remoção da string 'kakadu ...' da variável resulta em uma string -z empty. Se não, então novamente emite um erro e sai do shell. Se o seu shell ainda existir neste ponto, qualquer coisa após o bloqueio ser executado, caso contrário não é.

Provavelmente, esse tipo de coisa é melhor implementado em uma função. Como:

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
)

Com essa função, você pode fornecer quantos argumentos o seu sistema permitir. Se você fornecer menos de 2, ele retornará 1 e emitirá uma mensagem para stderr . Se você fornecer 2 ou mais argumentos, ele tratará todos como strings e retornará 0 se todos forem idênticos e não nulos, retornará o número do argumento que falhar primeiro na verificação.

No seu caso, pode ser usado como:

{   
    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

Para demonstrar mais, escreverei outra função:

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
}  

OUTPUT:

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
    
por 17.07.2014 / 20:24