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?
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?
Jawaban:
Cara lain untuk menggunakan let
bash builtin:
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
Catatan
Seperti yang ditunjukkan oleh @ Stéphane Chazelas , bash
Anda harus menggunakannya ((...))
untuk melakukan aritmatika expr
atau let
untuk keterbacaan.
Untuk portabilitas, gunakan jawaban$((...))
seperti @Bernhard .
let
. Ini tidak lebih standar atau portabel daripada (( a = 3 * (2 + 1) ))
(keduanya berasal dari ksh
dan hanya tersedia dalam ksh, bash dan zsh) dan kurang mudah dibaca atau mudah dikutip. Gunakan a=$((3 * (2 + 1)))
untuk menjadi portabel.
((a = 3 * (2 + 1) ))
, satu untuk portabilitas a=$((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]
atau a=1 b=2 $[a+b]
. Apakah alasan mereka menghindari sintaksis itu?
Anda dapat menggunakan ekspansi aritmatika saja.
echo "$(( 3 * ( 2 + 1 ) ))"
9
Menurut pendapat pribadi saya, ini terlihat sedikit lebih bagus daripada menggunakan expr
.
Dari man bash
Ekspansi Aritmatika Ekspansi aritmatika memungkinkan evaluasi ekspresi aritmatika dan substitusi hasilnya. Format untuk ekspansi aritmatika adalah:
$((expression))
Ekspresi diperlakukan seolah-olah itu dalam tanda kutip ganda, tetapi tanda kutip ganda di dalam tanda kurung tidak diperlakukan secara khusus. Semua token dalam ekspresi mengalami ekspansi parameter, ekspansi string, penggantian perintah, dan penghapusan kutipan. Ekspansi aritmatika mungkin bersarang.
Evaluasi dilakukan sesuai dengan aturan yang tercantum di bawah ini di bawah EVALUASI ARITHMETIC. Jika ekspresi tidak valid, bash mencetak pesan yang menunjukkan kegagalan dan tidak ada substitusi yang terjadi.
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 paling sh
disukai Unix, dash, bash, yash, mksh, zsh, posh, ksh ...).
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))
ksh
juga memperkenalkan let
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 di expr
:
if let 'a = 3 * (2 + 1)'; then
echo "$a is non-zero"
fi
Namun, karena kutipan membuatnya canggung dan tidak terlalu terbaca (tidak pada tingkat yang sama seperti expr
tentu saja), ksh
juga memperkenalkan ((...))
bentuk alternatif:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
echo "$a is non-zero and 3 > 1"
fi
((a+=2))
yang jauh lebih mudah dibaca dan harus digunakan sebagai gantinya.
let
dan ((...))
hanya tersedia di ksh
, zsh
dan bash
. 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):
@ a = 3 * (2 + 1)
akanga
(berdasarkan rc
)
a = $:'3 * (2 + 1)'
sebagai catatan sejarah, versi asli dari shell Almquist, seperti yang diposting di usenet pada tahun 1989 memiliki expr
builtin (sebenarnya digabung dengan test
), tetapi dihapus kemudian.
: $((a = a*2))
?
$((...))
seperti zsh, ksh93 atau yash.
expr
adalah perintah eksternal, itu bukan sintaks shell khusus. Oleh karena itu, jika Anda ingin expr
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:
expr 3 \* \( 2 + 1 \)
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 memanggil expr
utilitas sebagai gantinya. Semua cangkang POSIX memiliki aritmatika bawaan melalui sintaksis ekspansi aritmatika .
echo "$((3 * (2 + 1)))"
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.
((x = 3 * (2+1)))
echo "$x"
if ((x > 3)); then …
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.
expr foo : '\(.\)'
juga melakukan ekstraksi teks. bash
's BASH_REMATCH
mencapai sesuatu yang serupa. Ia juga melakukan perbandingan string, yang POSIX [
tidak lakukan (walaupun orang bisa membayangkan cara untuk menggunakannya sort
).
Gunakan tanda kurung dengan tanda kutip:
expr 3 '*' '(' 2 '+' 1 ')'
9
Kutipan mencegah bash menafsirkan kurung sebagai sintaks bash.
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.