Membandingkan dua string dalam Bash

22

Saya memiliki ifblok berikut dalam skrip bash saya:

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

Eksekusi skrip tidak memasuki ifblok saya meskipun $PACKAGENAMEsama dengan kakadu-v6_4-00902C. Apa yang saya lakukan salah?

DemiSheep
sumber
9
-eqberlaku untuk bilangan bulat, Anda ingin menguji string atau regex ( ==atau =~): mywiki.wooledge.org/BashGuide/TestsAndConditionals
jasonwryan
Terima kasih jasonwryansaya akan melihat sumber ini!
DemiSheep

Jawaban:

31

-eq adalah operator aritmatika, yang membandingkan dua angka.

Gunakan =(portable / standar sh), =~atau ==sebagai gantinya.

Juga gunakan tanda kutip, karena jika ${PACKAGENAME}berisi karakter spasi atau karakter pengganti, maka itu akan dibagi menjadi beberapa argumen, yang menyebabkan [lebih banyak argumen terlihat dari yang diinginkan. Lihat di sini daftar perangkap bash umum.

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

Lihat man bash, cari ( /) untuk CONDITIONAL EXPRESSIONS.

polym
sumber
1
Ah! Terima kasih! Berhasil! Saya jelas pemula dalam hal ini. Saya berterima kasih atas bantuan Anda!
DemiSheep
2
Sudahkah Anda melihat tldp.org/LDP/Bash-Beginners-Guide/html ? Ini panduan bash yang sangat bagus dan akan membantu Anda dengan contoh dan ujian :).
polym
1
Terima kasih polymsaya akan memeriksanya, terima kasih untuk sumber dayanya! Saya akan membuka tab itu di sebelah panduan VI saya. :)
DemiSheep
4
Di dalam tanda kurung ganda, tidak ada pemisahan kata yang dilakukan, begitu [[ $PACKAGENAME == "kakadu..." ]]juga OK.
glenn jackman
4
@glennjackman Namun berhati-hatilah bahwa bahkan di dalam tanda kurung ganda, Anda perlu tanda kutip ganda di sekitar ekspansi variabel di sisi kanan =, ==dan !=, karena sisi itu adalah pola, bukan string. Sebagai contoh, foo='*'; [[ whatever = $foo ]]itu benar.
Gilles 'SANGAT berhenti menjadi jahat'
6

Ganti -eqdengan == demikian jika blok Anda adalah ini: -

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

        echo "successfully entered if block!!"

fi
pemula
sumber
5
Jangan lupa mengutip! Silakan
polym
@polym, terima kasih, tapi saya hanya memberikan versi minimalis yang berfungsi;): D.
beginer
4

Cara lain adalah dengan meniadakannya:

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

Blok di atas tes pertama jika "$PACKAGENAME"memiliki nilai sama sekali, dan, jika tidak keluar dengan kesalahan dan gema ?'this'}untuk stderr. Jika shell induknya masih ada maka tes telah lulus, dan tes berikutnya akan menghapus string 'kakadu ...' Anda dari variabel yang menghasilkan -zstring kosong. Jika tidak, maka ia memancarkan kesalahan dan keluar dari shell. Jika shell Anda masih ada pada titik ini apa pun setelah blok dieksekusi, kalau tidak, shell tidak.

Mungkin hal semacam ini paling baik diimplementasikan dalam suatu fungsi. Seperti:

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
)

Dengan fungsi itu Anda dapat memberikan argumen sebanyak yang diizinkan oleh sistem Anda. Jika Anda memberikan kurang dari 2, itu akan mengembalikan 1 dan mengirim pesan ke stderr. Jika Anda memberikan 2 atau lebih argumen, itu akan memperlakukan semua sebagai string dan mengembalikan 0 jika semua sama dan bukan nol, itu akan mengembalikan nomor argumen yang pertama gagal cek.

Dalam kasus Anda dapat digunakan seperti:

{   
    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

Untuk menunjukkan lebih lanjut, saya akan menulis fungsi lain:

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
}  

KELUARAN:

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
sumber