Saat mendereferensi variabel dalam bash
, Anda harus menggunakan $
tanda. Namun demikian, tampaknya yang berikut ini berfungsi dengan baik:
x=5
[[ x -gt 2 ]]
Adakah yang bisa menjelaskan ini?
Edit: (info lebih lanjut)
Yang saya maksud adalah bagaimana dan mengapa perintah [[]] men-dereferensi variabel saya x tanpa tanda $. Dan ya, jika x = 1, pernyataan dievaluasi ke false (status pengembalian 1)
bash
bash-expansion
Tamu
sumber
sumber
x=1
diikuti[[ x -gt 2]]
?Jawaban:
Alasannya adalah bahwa
-eq
kekuatan evaluasi aritmatika argumen.Operator aritmatika:
-eq
,-gt
,-lt
,-ge
,-le
dan-ne
di dalam[[ ]]
(di ksh, zsh dan bash) alat untuk secara otomatis memperluas nama variabel seperti dalam bahasa c, tidak perlu untuk memimpin$
.Untuk konfirmasi, kita harus melihat kode sumber bash. Manual tidak menawarkan konfirmasi langsung .
Di
test.c
dalam pemrosesan operator aritmatika termasuk dalam fungsi ini:Di mana
s
dant
keduanya operan. Operan diserahkan ke fungsi ini:Fungsi
evalexp
didefinisikan di dalamexpr.c
, yang memiliki tajuk ini:Jadi, ya, kedua sisi operator aritmatika jatuh (langsung) ke dalam evaluasi ekspresi aritmatika. Secara langsung, tidak ada tetapi, tidak ada.
Dalam praktiknya, dengan:
Keduanya gagal:
Yang benar,
x
tidak diperluas danx
tidak sama dengan angka.Namun:
Variabel bernama
x
akan diperluas (bahkan tanpa $).Ini tidak terjadi untuk
[…]
di zsh atau bash (tidak di ksh).Itu sama dengan apa yang terjadi di dalam
$((…))
:Dan, harap dipahami bahwa ini (sangat) rekursif (kecuali dalam tanda hubung dan yash):
A 😮
Dan cukup berisiko:
Kesalahan sintaksis dapat dengan mudah dihindari:
Seperti kata pepatah: membersihkan input Anda
akhir 😮
Baik eksternal (lama)
/usr/bin/test
(bukan builtintest
) dan yang masih lebih tua dan juga eksternalexpr
tidak memperluas ekspresi hanya bilangan bulat (dan tampaknya, hanya bilangan bulat desimal):sumber
[[
kata kunci, operator dan operan terdeteksi ketika perintah dibaca dan bukan setelah ekspansi. Dengan demikian[[
dapat memperlakukan-eq
dengan cara yang lebih pintar daripada, katakanlah[
,. Tapi yang saya ingin tahu adalah: di mana kita dapat menemukan dokumentasi tentang penggunaan logika bash untuk menafsirkan perintah majemuk? Tidak terlihat jelas bagi saya dan saya tampaknya tidak dapat menemukan penjelasan yang memuaskan diman
atauinfo bash
.test
bagian manusia zshbuiltins operator aritmatika berharap bilangan bulat argumen daripada ekspresi aritmatika . Yang menegaskan bahwa beberapa argumen diperlakukan sebagai ekspresi aritmatika oleh tes yang dibangun di bawah kondisi yang tidak ditentukan dalam kutipan ini. Saya akan mengkonfirmasi dengan kode sumber .... ...Operan dari perbandingan numerik
-eq
,-gt
,-lt
,-ge
,-le
dan-ne
diambil sebagai ekspresi aritmatika. Dengan beberapa batasan, mereka masih perlu kata-kata shell tunggal.Perilaku nama variabel dalam ekspresi aritmatika dijelaskan dalam Aritmatika Shell :
dan juga:
Tetapi saya tidak dapat menemukan bagian dari dokumentasi di mana dikatakan bahwa perbandingan numerik mengambil ekspresi aritmatika. Itu tidak dijelaskan dalam Konstruk Kondisional di bawah
[[
, juga tidak dijelaskan dalam Ekspresi Bersyarat Bash .Tetapi, dengan eksperimen, tampaknya berfungsi seperti yang dikatakan di atas.
Jadi, hal-hal seperti ini berfungsi:
ini juga (nilai variabel dievaluasi):
Tetapi ini tidak; itu bukan kata shell tunggal ketika
[[ .. ]]
diuraikan, jadi ada kesalahan sintaksis dalam kondisi:Dalam konteks aritmatika lainnya, ekspresi tidak perlu tanpa spasi putih. Ini mencetak
999
, karena tanda kurung secara jelas membatasi ekspresi aritmatika dalam indeks:Di sisi lain,
=
perbandingannya adalah kecocokan pola , dan tidak melibatkan aritmatika, maupun ekspansi variabel otomatis yang dilakukan dalam konteks aritmatika (Konstruk Kondisional):Jadi ini salah karena senarnya jelas berbeda:
seperti ini, meskipun nilai numeriknya sama:
dan di sini juga, senar (
x
dan6
) dibandingkan, mereka berbeda:Ini akan memperluas variabel, jadi ini benar:
sumber
arg1 OP arg2
mengatakan bahwa argumen mungkin bilangan bulat positif atau negatif, yang saya kira seharusnya menyiratkan bahwa mereka diperlakukan sebagai ekspresi aritmatika. Yang membingungkan, itu juga menyiratkan bahwa mereka tidak boleh nol. :)[
juga, dan tidak ada ekspresi aritmatika. Sebaliknya, Bash mengeluh tentang non-bilangan bulat.[
adalah perintah eksternal, ia tidak memiliki akses ke variabel shell. Ini sering dioptimalkan dengan perintah bawaan, tetapi masih berlaku sama.[
juga[[
. Bahkan dengan[
, operan ke-eq
dan teman harus / harus bilangan bulat, sehingga deskripsi juga berlaku. Mengambil "harus bilangan bulat" berarti "ditafsirkan sebagai ekspresi aritmatika" tidak berlaku dalam kedua kasus. (Mungkin setidaknya sebagian karena[
bertindak seperti perintah biasa, seperti yang Anda katakan.)Ya, pengamatan Anda benar, ekspansi variabel dilakukan pada ekspresi di bawah tanda kurung ganda
[[ ]]
, jadi Anda tidak perlu meletakkan$
di depan nama variabel.Ini secara eksplisit dinyatakan dalam
bash
manual:Perhatikan bahwa ini bukan kasus versi braket tunggal
[ ]
, karena[
bukan kata kunci shell (sintaks), melainkan sebuah perintah (dalam bash itu dibangun di dalam, shell lain dapat menggunakan eksternal, dilapisi untuk menguji).sumber
(x=1; [[ $x = 1 ]]; echo $?)
pengembalian0
,(x=1; [[ x = 1 ]]; echo $?)
pengembalian1
, yaitu ekspansi parameter tidak dilakukanx
ketika kita membandingkan string. Perilaku ini seperti evaluasi aritmatika yang dipicu oleh ekspansi aritmatika, yaitu apa yang terjadi di(x=1; echo $((x+1)))
. (Tentang evaluasi aritmatika,man bash
nyatakan bahwa "Dalam sebuah ekspresi, variabel shell juga dapat dirujuk dengan nama tanpa menggunakan sintaksis ekspansi parameter).-gt
operator mengharapkan angka sehingga seluruh ekspresi dievaluasi kembali seolah-olah di dalam(())
, di sisi lain==
mengharapkan string sehingga alih-alih fungsi pencocokan pola dipicu. Saya tidak menggali ke dalam kode sumber, tetapi kedengarannya masuk akal.[
adalah shell builtin dalam bash.