expr
tampaknya tidak menyukai tanda kurung (digunakan dalam matematika untuk prioritas operator eksplisit):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
Bagaimana cara mengekspresikan prioritas operator dalam bash?
shell
quoting
arithmetic
expr
Nicolas Raoul
sumber
sumber
let
. Ini tidak lebih standar atau portabel daripada(( a = 3 * (2 + 1) ))
(keduanya berasal dariksh
dan hanya tersedia dalam ksh, bash dan zsh) dan kurang mudah dibaca atau mudah dikutip. Gunakana=$((3 * (2 + 1)))
untuk menjadi portabel.((a = 3 * (2 + 1) ))
, satu untuk portabilitasa=$((3 * (2 + 1)))
), jadi itu bukan catatan terhadap Anda atau jawaban Anda tetapi menentangnya menjadi jawaban yang dipilih dan pencetak gol terbanyak.a=1 $[a+2]
ataua=1 b=2 $[a+b]
. Apakah alasan mereka menghindari sintaksis itu?Anda dapat menggunakan ekspansi aritmatika saja.
Menurut pendapat pribadi saya, ini terlihat sedikit lebih bagus daripada menggunakan
expr
.Dari
man bash
sumber
Tidak ada alasan untuk menggunakan
expr
aritmatika di kulit modern.POSIX mendefinisikan
$((...))
operator ekspansi. Jadi Anda dapat menggunakannya di semua shell yang sesuai dengan POSIX (yang palingsh
disukai Unix, dash, bash, yash, mksh, zsh, posh, ksh ...).ksh
juga memperkenalkanlet
builtin yang dilewatkan dengan jenis ekspresi aritmatika yang sama, tidak berkembang menjadi sesuatu tetapi mengembalikan status keluar berdasarkan apakah ekspresi diselesaikan ke 0 atau tidak, seperti diexpr
:Namun, karena kutipan membuatnya canggung dan tidak terlalu terbaca (tidak pada tingkat yang sama seperti
expr
tentu saja),ksh
juga memperkenalkan((...))
bentuk alternatif:yang jauh lebih mudah dibaca dan harus digunakan sebagai gantinya.
let
dan((...))
hanya tersedia diksh
,zsh
danbash
. The$((...))
sintaks harus disukai jika portabilitas untuk kerang lainnya diperlukan,expr
hanya diperlukan untuk kerang pre-POSIX Bourne-seperti (biasanya Bourne shell atau versi awal dari Almquist shell).Di bagian depan non-Bourne, ada beberapa cangkang dengan operator aritmatika bawaan:
csh
/tcsh
(sebenarnya shell Unix pertama dengan built-in evaluasi aritmatika):akanga
(berdasarkanrc
)sebagai catatan sejarah, versi asli dari shell Almquist, seperti yang diposting di usenet pada tahun 1989 memiliki
expr
builtin (sebenarnya digabung dengantest
), tetapi dihapus kemudian.sumber
: $((a = a*2))
?$((...))
seperti zsh, ksh93 atau yash.expr
adalah perintah eksternal, itu bukan sintaks shell khusus. Oleh karena itu, jika Anda inginexpr
melihat karakter khusus shell, Anda perlu melindungi mereka dari penguraian shell dengan mengutipnya. Selain itu,expr
perlu setiap nomor dan operator untuk dilewatkan sebagai parameter terpisah. Jadi:Kecuali jika Anda mengerjakan sistem unix antik dari tahun 1970-an atau 1980-an, hanya ada sedikit alasan untuk menggunakannya
expr
. Di masa lalu, shell tidak memiliki cara bawaan untuk melakukan aritmatika, dan Anda harus memanggilexpr
utilitas sebagai gantinya. Semua cangkang POSIX memiliki aritmatika bawaan melalui sintaksis ekspansi aritmatika .Konstruk
$((…))
memperluas ke hasil ekspresi aritmatika (ditulis dalam desimal). Bash, seperti kebanyakan shell, hanya mendukung bilangan bulat modulo 2 64 (atau modulo 2 32 untuk versi bash yang lebih lama dan beberapa shell lainnya pada mesin 32-bit).Bash menawarkan sintaks kenyamanan tambahan ketika Anda ingin melakukan tugas atau untuk menguji apakah ekspresi 0 tetapi tidak peduli dengan hasilnya. Konstruk ini juga ada di ksh dan zsh tetapi tidak di sh polos.
Selain aritmatika integer,
expr
menawarkan beberapa fungsi manipulasi string. Ini juga digolongkan oleh fitur-fitur shell POSIX, kecuali untuk satu:expr STRING : REGEXP
menguji apakah string cocok dengan regexp yang ditentukan. Shell POSIX tidak dapat melakukan ini tanpa alat eksternal, tetapi bash can dengan[[ STRING =~ REGEXP ]]
(dengan sintaksis regexp yang berbeda -expr
adalah alat klasik dan menggunakan BRE, bash menggunakan ERE).Kecuali jika Anda mengelola skrip yang berjalan pada sistem berusia 20 tahun, Anda tidak perlu tahu itu
expr
pernah ada. Gunakan aritmatika shell.sumber
expr foo : '\(.\)'
juga melakukan ekstraksi teks.bash
'sBASH_REMATCH
mencapai sesuatu yang serupa. Ia juga melakukan perbandingan string, yang POSIX[
tidak lakukan (walaupun orang bisa membayangkan cara untuk menggunakannyasort
).Gunakan tanda kurung dengan tanda kutip:
Kutipan mencegah bash menafsirkan kurung sebagai sintaks bash.
sumber
expr
baris perintah harus dipisahkan oleh spasi; begitu; misalnya,expr 3 "*" "(2" "+" "1)"
tidak akan berfungsi . (Juga, BTW, Anda mungkin tidak perlu mengutipnya+
.)while
dan[[
, itu adalah sintaks. Jika mereka adalah kata kunci, mereka tidak akan ditafsirkan seperti itu dalam argumen perintah. Anda membutuhkan tanda kutip agar bash tidak menguraikannya tetapi sebaliknya melihat string literal.Jika Anda memiliki bc ..
sumber