Shell Script - kesalahan sintaksis dekat token yang tidak terduga `else '

15

Dengan skrip shell berikut, mengapa saya mendapatkan kesalahan

syntax error near unexpected token `else'

Script Shell

echo "please enter username"
read user_name
echo "please enter password"
read -s pass
echo ${ORACLE_SID}
SID=${ORACLE_SID}
if ["${ORACLE_SID}" != 'Test'] then
sqlplus -s -l $USER_NAME/$PASS@$SID <<EOF
copy from scott/tiger@orcl insert EMP using select * from EMP
exit
EOF
else
echo "Cannot copy"
fi
Jåcob
sumber
Anda mungkin ingin mengedit baris "salin dari ...." karena saat ini mungkin menampilkan sesuatu yang tidak ingin Anda tampilkan. (Namun, saya berharap itu sudah diubah info, karena mereka akan sangat miskin keamanan bijaksana)
Olivier Dulac
1
@OlivierDulac Jika Anda mengacu pada nama pengguna dan kata sandi di baris itu, maka itu dikenal oleh semua pengguna basis data Oracle. Ini umum dan terkenal sejak awal database Oracle.
Jåcob
@OlivierDulac Anda dipersilakan, beberapa info tentang dba-oracle.com/t_scott_tiger.htm
Jåcob

Jawaban:

25

Anda harus mengakhiri kondisi ifseperti ini:

if [ "${ORACLE_SID}" != 'Test' ]; then

atau seperti ini:

if [ "${ORACLE_SID}" != 'Test' ]
then

Catatan: Anda juga harus meletakkan spasi setelah [dan sebelum ].

Alasan untuk ;atau linebreak adalah bahwa bagian kondisi ifpernyataan hanyalah sebuah perintah. Perintah apa pun dengan panjang berapa pun harus tepat. Shell mengeksekusi perintah itu, memeriksa status keluar dari perintah, dan kemudian memutuskan apakah akan mengeksekusi thenbagian atau elsebagian.

Karena perintah dapat panjang berapa pun, perlu ada penanda untuk menandai akhir dari bagian kondisi. Itu adalah ;atau baris baru, diikuti oleh then.

Alasan spasi setelah [ adalah karena [merupakan perintah. Biasanya builtin dari shell. Shell mengeksekusi perintah [dengan sisanya sebagai parameter, termasuk ]sebagai parameter terakhir yang wajib. Jika Anda tidak memberi spasi setelah [shell akan mencoba mengeksekusi [whateversebagai perintah dan gagal.

Alasan ruang sebelum ] itu serupa. Karena kalau tidak maka ia tidak akan dikenali sebagai parameternya sendiri.

lesmana
sumber
Itu tepat, tetapi sekarang saya mulai test.sh: line 6: [: missing ] ''
Jåcob
@lesmana. Cara yang baik untuk memberikan jawaban yang salah terlebih dahulu, kemudian terus mengedit sebelum orang lain memberikan jawaban yang benar. Harap coba berikan jawaban yang benar pertama kali.
Valentin Bajrami
1
Saya tidak menganggap jawaban pertama saya salah. Bahkan, itu "tepat". Itu hanya tidak menyelesaikan semua masalah dalam pertanyaan.
lesmana
if adalah sintaks, itu bukan perintah biasa. Itu kata yang dilindungi undang-undang. Tidak seperti banyak bahasa pemrograman lain, shell tidak mengenali kata-kata yang dilindungi undang-undang di mana-mana, hanya ketika mereka adalah kata pertama dari sebuah perintah (dengan beberapa seluk-beluk).
Gilles 'SANGAT berhenti menjadi jahat'
Terimakasih atas klarifikasinya. Saya sadar itu ifsintaks. Saya mencoba untuk berkomunikasi bahwa kondisi bagian iftidak dibatasi oleh bentuk tertentu oleh sintaks. Saya telah mengedit teks. Saya harap ini lebih jelas sekarang.
lesmana
5

Anda dapat dengan mudah memeriksa skrip shell menggunakan ShellCheck online (juga tersedia sebagai alat mandiri).

Dalam hal ini, ini akan menunjukkan bahwa pernyataan-if membutuhkan spasi, setelah [dan sebelum ], dan bahwa Anda memerlukan a; (atau baris baru) sebelum thenbaris yang sama.

Ketika Anda sudah memperbaikinya, itu akan memberitahu Anda bahwa USER_NAMEitu digunakan tanpa diinisialisasi dengan apa pun. Ini karena Anda juga memiliki user_namevariabel (hal-hal penting). Hal yang sama berlaku untukPASS dan pass.

Ini juga memberi tahu Anda untuk menggunakan read -ragar berhenti readdari mangling \(misalnya, penting untuk kata sandi), dan Anda harus menggandakan penawaran variabel saat menelepon sqlplusuntuk mencegah shell secara tidak sengaja melakukan penggumpalan nama file dan pemisahan kata (sekali lagi ini penting jika kata sandi, misalnya, berisi karakter seperti globbing file *, atau spasi).

Indentasi kode akan membuatnya lebih mudah dibaca juga:

#!/bin/bash

read -r -p 'please enter username: ' user_name
IFS= read -rs -p 'please enter password: ' pass

printf 'ORACLE_SID = %s\n' "$ORACLE_SID"
sid=$ORACLE_SID

if [ "$sid" = 'Test' ]; then
    echo 'Cannot copy' >&2
    exit 1
fi

sqlplus -s -l "$user_name/$pass@$sid" <<'SQL_END'
copy from scott/tiger@orcl insert EMP using select * from EMP
exit
SQL_END

Di sini saya juga memungkinkan untuk menggunakan kata sandi dengan karakter spasi memimpin atau tertinggal dengan mengatur sementara IFSke string kosong untuk membaca kata sandi read.

Logikanya juga berubah untuk menyelamatkan jika $ORACLE_SID/ $sidadalah Test. Ini menghindari memiliki bagian operasional utama skrip di ifcabang.

Kusalananda
sumber
Perhatikan itu if ([ x = x ]) then (echo yes) fijuga berfungsi.
Stéphane Chazelas
@ StéphaneChazelas Ah, ya. Dan itu mungkin menarik dari sudut pandang suatu program yang menghasilkan kode shell, tetapi itu bukan bagaimana orang biasanya menulis ifpernyataan dengan [ ... ]... :-)
Kusalananda
2

Saat menulis shAnda inginkan

if [ "$ORACLE_SID" != "Test" ]
then
  ...
fi

Saat menulis bash

if [[ "$ORACLE_SID" != "Test" ]]
then
  ...
fi

Tolong pikirkan ruangnya. Harus ada ruang antara [[dan operator pertama.

Valentin Bajrami
sumber