GNU/Linux >> Belajar Linux >  >> Linux

Mengapa Bash `(())` tidak berfungsi di dalam `[[]]`?

Halaman manual bash GNU untuk [[..]] menjelaskan bahwa operator menjalankan ekspresi bersyarat dan

Kembalikan status 0 atau 1 tergantung pada evaluasi ekspresi kondisional expression . Ekspresi terdiri dari pendahuluan yang dijelaskan di bawah dalam Bash Conditional Expressions.

Tapi operator aritmatika tidak bagian dari ekspresi bersyarat yang didukung (primer ) di dalam [[..]] yang berarti ekspresi dipaksa untuk dijalankan sebagai perbandingan string, yaitu

(( $n < 3))

tidak dijalankan dalam konteks aritmatika tetapi hanya perbandingan leksikografis (string) biasa seperti

[[ 100 < 3 ]] 

yang hasilnya akan selalu benar, karena nilai ASCII untuk 1 , 0 , 0 muncul sebelum 3

Tapi di dalam [[..]] operasi aritmatika didukung jika Anda menggunakan -lt , -gt

arg1 OP arg2

OP adalah salah satu dari -eq , -ne , -lt , -le , -gt , atau -ge . Operator biner aritmetika ini menghasilkan true jika arg1 sama dengan, tidak sama dengan, kurang dari, kurang dari atau sama dengan, lebih besar dari, atau lebih besar dari atau sama dengan arg2 , masing-masing.

Jadi apakah Anda menulis ekspresi Anda sebagai

a=start; n=100; [[ " stop start status " =~ " $a " && $n -lt 3 ]] && echo ok || echo bad
bad

itu akan berfungsi seperti yang diharapkan.

Atau bahkan jika Anda telah memaksakan penggunaan ekspresi aritmatika dengan mengawali $ sebelum ((..)) dan tulis seperti di bawah ini (perhatikan bahwa bash tidak mendokumentasikan perilaku untuk $((..)) di dalam [[..]] ). Kemungkinan perilaku yang diharapkan adalah ekspresi aritmatika diperluas sebelum [[..]] dievaluasi dan keluaran yang dihasilkan dievaluasi dalam konteks string sebagai [[ 0 ]] yang berarti string yang tidak kosong.

a=start; n=5; [[ " stop start status " =~ " $a " && $(( $n < 3 )) ]] && echo ok || echo bad

Hasilnya akan tetap terlihat buruk, karena ekspresi aritmetika di dalam [[..]] terurai menjadi string unary bukan ekspresi perbandingan kosong sebagai

$(( 5 < 3 ))
0
[[ -n 0 ]]

Hasil evaluasi aritmatika 0 (salah) diambil sebagai entitas bukan nol oleh operator pengujian dan dinyatakan benar di sisi kanan && . Hal yang sama juga berlaku untuk kasus lain, mis. ucapkan n=1

$(( 1 < 3 ))
1
[[ -n 1 ]]

Singkat cerita, gunakan operan yang tepat untuk operasi aritmatika di dalam [[..]] .


(( adalah "kata kunci" yang memperkenalkan pernyataan aritmatika. Di dalam [[ , namun, Anda tidak dapat menggunakan pernyataan lain. Anda bisa gunakan tanda kurung untuk mengelompokkan ekspresi, jadi itulah (( ... )) adalah:"grup ganda" yang berlebihan. Berikut ini semuanya setara, karena mendahului < dan && :

  • [[ " stop start status " =~ " $2 " && (($#<3)) ]]
  • [[ " stop start status " =~ " $2 " && ($#<3) ]]
  • [[ " stop start status " =~ " $2 " && $#<3 ]]

Jika Anda ingin perbandingan bilangan bulat, gunakan -lt bukannya < , tetapi Anda juga tidak perlu memasukkan semuanya ke dalam [[ ... ]] . Anda dapat menggunakan pernyataan bersyarat dan pernyataan aritmetika secara bersamaan dalam daftar perintah.

{ [[ " stop start status " =~ " $2 " ]] && (($#<3)) ; } || { echo "Usage $0 file_name command"; exit 1;}

Dalam hal ini, ... && ... || ... akan bekerja seperti yang Anda harapkan, meskipun secara umum tidak demikian. Lebih suka if pernyataan sebagai gantinya.

if [[ " stop start status " =~ " $2 " ]] && (($#<3)); then
  echo "Usage $0 file_name command"
  exit 1
fi

Linux
  1. Mengapa ~/.bash_profile Tidak Berfungsi?

  2. Mengapa Pelengkapan Otomatis Tidak Berfungsi Saat Mengetik Nama Perintah Setelah `sumber`?

  3. Mengapa Dokumen Induk Shell Di Sini Tidak Berfungsi Untuk Sub-perintah Di Dash Tapi Bash Bekerja?

  1. Mengapa `keluar &` Tidak Berfungsi?

  2. LD_LIBRARY_PATH sepertinya tidak berfungsi

  3. Mengapa `\d` tidak berfungsi dalam ekspresi reguler di sed?

  1. Mengapa hostname --fqdn tidak berfungsi di komputer Ubuntu saya?

  2. Mengapa tautan simbolik saya tidak berfungsi?

  3. mengapa bash while loop tidak keluar saat menyalurkan ke subperintah yang diakhiri?