Порівняння двох рядків у 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/TestsAndConditionss
jasonwryan

Дякую, jasonwryanя погляну на цей ресурс!
DemiSheep

Відповіді:


31

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

Використовуйте =(портативний / стандартний sh) =~або ==замість цього.

Також використовуйте лапки, тому що якщо ${PACKAGENAME}міститься пробіл або символ символів, то він буде розділений на кілька аргументів, що змушує [переглянути більше аргументів, ніж бажано. Дивіться тут список загальних підводних каменів.

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 ? Це дуже приємний посібник з баш та допоможе вам у прикладах та іспитах :).
полім

1
Дякую, polymя погляну, дякую за ресурс! Я відкрию цю вкладку поруч зі своїм VI керівництвом. :)
DemiSheep

4
У подвійних дужках розділення слів не проводиться, так що [[ $PACKAGENAME == "kakadu..." ]]це нормально.
glenn jackman

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

6

Замінити -eqз , == так що ваші , якщо блок буде наступним чином : -

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 привіт, але я просто дав мінімалістичну версію, яка працювала;): 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.