Kabuk Betiği - `` else '' beklenmeyen belirtecinin yanında sözdizimi hatası


15

Aşağıdaki kabuk betiğiyle neden hata alıyorum

syntax error near unexpected token `else'

Kabuk Betiği

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


şu anda göstermek istemediğiniz bir şeyi gösteriyor olabileceği için "kopyalanacak yer ...." satırını düzenlemek isteyebilirsiniz. (Ancak, umarım bunlar zaten değiştirilmiş bilgilerdir, çünkü bunlar gerçekten zayıf güvenlik açısından akıllıca olacaktır)
Olivier Dulac

1
@OlivierDulac Bu satırdaki kullanıcı adı ve şifreye atıfta bulunuyorsanız, bunlar tüm Oracle veritabanı kullanıcıları tarafından bilinir. Oracle veritabanının başlangıcından beri yaygın ve iyi bilinmektedir.
Jåcob

@OlivierDulac Hoş geldiniz, bu dba-oracle.com/t_scott_tiger.htm
Jåcob

Yanıtlar:


26

Böyle bir şeye son vermelisiniz if:

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

ya da bunun gibi:

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

Not: [Önce ve sonra boşluk bırakmanız gerekir ].

;Veya satır kırılmasının nedeni , ififadenin koşul bölümünün yalnızca bir komut olmasıdır. Herhangi bir uzunlukta herhangi bir komutun kesin olması. Kabuk bu komutu yürütür, komutun çıkış durumunu inceler ve sonra thenparçanın mı yoksa parçanın mı yürütüleceğine karar verir else.

Komut herhangi bir uzunlukta olabileceğinden, koşul parçasının sonunu işaretlemek için bir işaretleyici olması gerekir. Bunu ;ya da yeni satır takip eder then.

Sonraki boşlukların [nedeni [bir komut olmasıdır. Genellikle kabuğun bir yerleşimi. Kabuk, komutu zorunlu son parametre [de dahil olmak üzere geri kalanıyla parametre olarak yürütür ]. Kabuktan sonra boşluk bırakmazsanız komut olarak [çalıştırmayı dener [whateverve başarısız olur.

Önündeki boşluğun nedeni ]benzer. Aksi takdirde, kendi parametresi olarak tanınmayacaktır.


Bu noktadaydı, ancak şimdi alıyorum test.sh: line 6: [: missing ] ''
Jåcob

@lesmana. Önce yanlış bir cevap vermenin iyi bir yolu, daha sonra bir başkası doğru cevabı vermeden önce düzenlemeye devam edin. Lütfen ilk kez doğru cevabı vermeye çalışın.
Valentin Bajrami

1
İlk cevabımı yanlış olarak görmüyorum. Aslında, "spot on" idi. Sadece sorudaki tüm sorunları çözmedi .
lesmana

if olduğu sıradan bir komut değil, sözdizimi. Ayrılmış bir kelime. Diğer birçok programlama dilinden farklı olarak, kabuk ayrılmış sözcükleri her yerde tanımaz, yalnızca bir komutun ilk sözcüğü olduklarında (birkaç incelikli).
Gilles 'SO- kötü olmayı bırak'

Açıklama için teşekkürler. Bunun ifsözdizimi olduğunun farkındayım . Ben durumu parçası ifsözdizimi ile belirli bir formla sınırlı olmadığını iletişim kurmaya çalışıyordu . Metni düzenledim. Umarım şimdi daha açıktır.
lesmana

5

Shell komut dosyalarınızı çevrimiçi olarak ShellCheck (bağımsız bir araç olarak da kullanılabilir) kullanarak kolayca kontrol edebilirsiniz .

Bu durumda, if-ifadesinin [önce ]ve sonra boşluklara ihtiyaç duyduğunu ve aynı satırdan ;önce bir (veya bir yeni satıra) ihtiyacınız olduğunu gösterecektir then.

Bunu düzelttiğinizde, USER_NAMEhiçbir şeye başlatılmadan kullanıldığını size söyleyecektir . Bunun nedeni bir user_namedeğişkeninizin de olması (büyük / küçük harf önemlidir). Aynı şey PASSve için de geçerlidir pass.

Ayrıca , mangling (örneğin şifreler için önemli olabilir) read -rdurdurmak için kullanmanız ve kabuğun yanlışlıkla dosya adı globbing ve kelime bölme yapmasını önlemek için arama yaparken değişkenleri iki kez alıntı yapmanız gerektiğini söyler (yine bu önemlidir parola, örneğin, boşluk veya boşluklar gibi dosya globbing karakterleri içerir ).read\sqlplus*

Kodu girintilemek de kodu daha okunabilir hale getirir:

#!/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

Burada ayrıca IFS, parola okumak için geçici olarak boş bir dizeye ayarlayarak önde gelen veya sondaki boşluk karakterlerine sahip şifreleri kullanmayı mümkün kıldım read.

Mantık, eğer $ORACLE_SID/ $sidise kefaletle değiştirilecek şekilde değiştirildi Test. Bu, betiğin ana operasyonel bölümünün bir ifdalda olmasını önler .


Bunun if ([ x = x ]) then (echo yes) fida işe yaradığını unutmayın .
Stéphane Chazelas

@ StéphaneChazelas Ah, evet. Ve bu, kabuk kodu üreten bir programın bakış açısından ilginç olabilir, ancak genellikle şöyle ififadeler yazar [ ... ]... :-)
Kusalananda

2

Yazarken shistersiniz

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

Yazarken bash

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

Boşluklara dikkat edin lütfen. [[İlk operatör ile arasında bir boşluk olmalıdır .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.