Agar aman, saya ingin bash membatalkan eksekusi skrip jika menemui kesalahan sintaksis.
Yang mengejutkan saya, saya tidak bisa mencapai ini. ( set -e
tidak cukup.) Contoh:
#!/bin/bash
# Do exit on any error:
set -e
readonly a=(1 2)
# A syntax error is here:
if (( "${a[#]}" == 2 )); then
echo ok
else
echo not ok
fi
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Hasil (bash-3.2.39 atau bash-3.2.51):
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 10: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Ya, kami tidak dapat memeriksa $?
setelah setiap pernyataan untuk mengetahui kesalahan sintaksis.
(Saya mengharapkan perilaku aman dari bahasa pemrograman yang masuk akal ... mungkin ini harus dilaporkan sebagai bug / keinginan untuk mem-bash pengembang)
Eksperimen lebih banyak
if
tidak ada bedanya.
Menghapus if
:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
(( "${a[#]}" == 2 ))
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Hasil:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Mungkin, ini terkait dengan latihan 2 dari http://mywiki.wooledge.org/BashFAQ/105 dan ada hubungannya dengan (( ))
. Tapi saya merasa masih tidak masuk akal untuk terus mengeksekusi kesalahan sintaks.
Tidak, (( ))
tidak ada bedanya!
Itu berperilaku buruk bahkan tanpa tes aritmatika! Hanya skrip dasar yang sederhana:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
echo "${a[#]}"
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Hasil:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
sumber
set -e
tidak cukup karena kesalahan sintaks Anda dalamif
pernyataan. Di tempat lain harus batalkan naskah.set -e
tidak berhasil. Tapi pertanyaan saya masih masuk akal. Apakah mungkin untuk membatalkan kesalahan sintaks?Jawaban:
Membungkus keseluruhan menjadi suatu fungsi tampaknya melakukan trik:
Hasil:
Meskipun saya tidak tahu mengapa - mungkin orang lain bisa menjelaskan?
sumber
echo 'Bad2: has not aborted the execution after bad main!'
sebagai yang terakhir pada contoh Anda, dan hasilnya adalah: $ LC_ALL = C./sh-on-syntax-err ./sh-on-syntax-err: baris 6: #: kesalahan sintaks: operan diharapkan (operand diharapkan) token kesalahan adalah "#") Bad2: belum membatalkan eksekusi setelah main buruk! $Anda mungkin menyesatkan tentang arti asli dari
set -e
. Pembacaan yang cermat dari outputhelp set
acara:Begitu
-e
juga tentang status keluar dari perintah yang bukan nol, bukan tentang kesalahan sintaksis dalam skrip Anda.Secara umum, ini dianggap praktik buruk untuk digunakan
set -e
, karena semua kesalahan (yaitu, semua pengembalian non-nol dari perintah) harus ditangani dengan cerdas oleh skrip (pikirkan skrip yang kuat, bukan skrip yang menjadi liar setelah Anda memasukkan nama file dengan ruang atau yang dimulai dengan tanda hubung).Bergantung pada jenis kesalahan sintaksis, skrip mungkin bahkan tidak dieksekusi sama sekali. Saya tidak cukup berpengetahuan di bash untuk mengetahui dengan tepat kelas kesalahan sintaksis apa (yang dapat diklasifikasikan) yang dapat menyebabkan aborsi skrip dengan segera atau tidak. Mungkin beberapa guru Bash akan bergabung dan menjelaskan semuanya.
Saya hanya berharap saya mengklarifikasi
set -e
pernyataan itu!Tentang keinginan Anda:
Jawabannya jelas tidak! seperti yang telah Anda amati (
set -e
tidak merespons seperti yang Anda harapkan) sebenarnya didokumentasikan dengan sangat baik.sumber
set -e
- hanya sedikit dekat dengan tujuan saya, itu sebabnya disebutkan dan digunakan di sini. Pertanyaan saya bukan tentangset -e
, ini tentang ketidakamanan bash jika tidak dapat dibuat untuk membatalkan kesalahan sytax. Saya mencari cara untuk membuatnya selalu gagal pada kesalahan sintaksis.Anda dapat membuat skrip memeriksa sendiri dengan meletakkan sesuatu seperti
di dekat bagian atas skrip - setelah
set -e
tetapi sebelum potongan kode yang signifikan.Saya harus mengatakan ini tidak terasa sangat kuat, tetapi jika itu bekerja untuk Anda, mungkin itu dapat diterima.
sumber
set -e
:bash -n "$0" || exit
Pertama,
(( ))
in bash digunakan sebagai perhitungan aritmatika, bukan untuk digunakan dalam if ... gunakan[]
untuk itu.Kedua, itu
${a[#]}
aneh dan itulah sebabnya memberikan kesalahan ...#
tidak memiliki arti arraySaya tidak tahu apa yang ingin Anda lakukan dengan ini, tetapi saya berasumsi Anda ingin tahu jumlah bidang, jadi Anda mau
${#a[*]}
gantinyaAkhirnya, ketika membandingkan bilangan bulat,
-eq
direkomendasikan lebih==
(digunakan untuk string). itu==
juga akan bekerja, tetapi-eq
dianjurkan.jadi kamu mau:
sumber
((
kata kunci denganif
kata kunci. Sebagai contohif (( 5 * $b > 53 ))
,. Kecuali Anda bertujuan untuk portabilitas dengan kerang yang lebih tua,[[
adalah umumnya lebih lebih[
.[[
dan((
dirancang khusus sebagai tes ringan untuk digunakan dengan "jika" dll - tidak seperti[
, mereka tidak pernah menelurkan subproses untuk mengevaluasi kondisinya.[
adalah bash builtin. Kerang yang lebih tua mengharapkannya menjadi programnya sendiri.