Сравнивая две строки в Bash


22

У меня есть следующий ifблок в моем скрипте bash:

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

Выполнение скрипта не входит в мой ifблок, хотя $PACKAGENAMEоно равно kakadu-v6_4-00902C. Что я делаю не так?


9
-eqистинно для целых чисел, вы хотите проверить строку или регулярное выражение ( ==или =~): mywiki.wooledge.org/BashGuide/TestsAndConditionals
jasonwryan

Спасибо, jasonwryanя посмотрю на этот ресурс!
DemiSheep

Ответы:


31

-eq является арифметическим оператором, который сравнивает два числа.

Используйте =(портативный / стандартный sh) =~или ==вместо.

Также используйте кавычки, потому что если ${PACKAGENAME}содержит пробел или подстановочный знак, то он будет разбит на несколько аргументов, что заставит [видеть больше аргументов, чем нужно . Смотрите здесь список распространенных ошибок Bash.

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

Смотрите man bash, ищите ( /) для CONDITIONAL EXPRESSIONS.


1
Ах! Спасибо! Это сработало! Я, очевидно, новичок в этом. Я благодарен за вашу помощь!
DemiSheep

2
Вы смотрели на tldp.org/LDP/Bash-Beginners-Guide/html ? Это очень хорошее руководство по bash, которое поможет вам с примерами и экзаменами :).
полим

1
Спасибо, polymя посмотрю, спасибо за ресурс! Я открою эту вкладку рядом с моим руководством по VI. :)
DemiSheep

4
В двойных скобках разделение слов не выполняется, так что [[ $PACKAGENAME == "kakadu..." ]]все в порядке.
Гленн Джекман

4
@glennjackman Однако помните, что даже в двойных скобках вам нужны двойные кавычки вокруг разложения переменных в правой части =, ==и !=, поскольку эта сторона является шаблоном, а не строкой. Например, foo='*'; [[ whatever = $foo ]]это правда.
Жиль "ТАК - перестань быть злым"

6

Замените -eqна == ваш блок if так: -

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

        echo "successfully entered if block!!"

fi

5
Не забывайте цитировать! Посмотрите здесь, почему: mywiki.wooledge.org/BashPitfalls#A.5B_.24foo_.3D_.22bar.22_.5D
polym

@polym эй спасибо, но я только что дал минималистскую версию, которая работала;): D.
начинающий

4

Другой способ - отрицать их:

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

Вышеприведенные блок первые тесты , если "$PACKAGENAME"имеет какое - либо значение вообще, и, если не он выходит с ошибкой и эхо - сигналов ?'this'}с stderr. Если его родительская оболочка все еще существует, то тест пройден, и затем он проверяет, приводит ли удаление строки 'kakadu ...' из переменной к -zпустой строке. Если это не так, то он снова выдает ошибку и выходит из оболочки. Если ваша оболочка все еще существует в этой точке, что-нибудь после выполнения блока, в противном случае это не так.

Вероятно, такого рода вещи лучше всего реализовать в функции. Подобно:

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
)

С помощью этой функции вы можете предоставить столько аргументов, сколько позволит ваша система. Если вы предоставите меньше 2, он вернет 1 и отправит сообщение stderr. Если вы предоставите 2 или более аргумента, он будет обрабатывать все как строки и вернет 0, если все они идентичны, а не ноль, иначе он вернет номер аргумента, который сначала не пройдет проверку.

В вашем случае это может быть использовано как:

{   
    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

Для демонстрации я напишу еще одну функцию:

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
}  

ВЫХОД:

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.