Bash sözdizimi hatası: beklenmeyen dosya sonu


102

Bash'de çok basit bir senaryo olduğu için beni affet. İşte kod:

#!/bin/bash
# june 2011

if [ $# -lt 3 -o $# -gt 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

sh file.sh çalıştırdıktan sonra:

sözdizimi hatası: beklenmeyen dosya sonu

Yanıtlar:


144

Bence file.sh, CRLF hat sonlandırıcıları ile.

Çalıştırmak

dos2unix file.sh

o zaman sorun çözülecektir.

Dos2unix'i ubuntu'ya şu şekilde kurabilirsiniz:

sudo apt-get install dos2unix

Bu sorunun arkasındaki sebep nedir? Genelde Windows üzerinde çalışıyorum ama betikleri unix sistemlerine aktarmam gerekiyor.
CMCDragonkai

Windows'ta yeni satır "\ r \ n", linux'ta ise "\ n" dir.
clyfish

8
@KeesdeKooter Söylemeyeceğim, çünkü bir şey sizin için işe yaramadı, onu eksi oyla vermelisiniz, açıkça 28 olumlu oy için işe yaradı. Basit bir benim için işe yaramadı. Bu nedenle, SO bir soruya birden çok yanıta izin verdi çünkü bir soruna birden fazla çözüm olabilir.
Jeff Wilbert

2
Notepad ++ düzenleyiciyi kullanmak Düzenle> EOL Dönüştürme> Eski Mac Formatı benim için çözdü.
raktale

Bash dosyanızı Notepad ++ ile düzenleyebiliyorsanız. Düzen-> EOL Dönüştürme-> Macintosh (CR) seçeneğine gidin. Windows işletim sistemi kullanıyor olsanız bile bunu Macintosh (CR) olarak değiştirin.
Juniar

133

Kontrol edilecek başka bir şey (az önce aklıma geldi):

  • tek satırlı işlevlerin gövdelerini noktalı virgülle sonlandırın

Yani bu masum görünen pasaj aynı hataya neden olacaktır:

die () { test -n "$@" && echo "$@"; exit 1 }

Aptal ayrıştırıcıyı mutlu etmek için:

die () { test -n "$@" && echo "$@"; exit 1; }

3
+1 Aşağıdaki gibi parantez içeren kod parçacıkları için de geçerlidir: [["$ #" == 1]] && [["$ arg" == [1,2,3,4]]] && printf "% s \ n "" filan "|| {printf "% s \ n" "blahblah"; kullanım; } ............ Daha önce tanımlanmış bazı 'kullanım' işlevini çağırdıktan hemen sonra, dalgalı parantezler içinde noktalı virgül olduğuna dikkat edin. Bunu unutmak size aynı sözdizimi hatasını verecektir: beklenmedik eof.
Cbhihe

başardın. Aslında basit olan şey, ;Every ifadesinin sona ermesi beklenmektedir, ;bu nedenle sonunda, örneğin: if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fibu hatayı üretecek, oysa if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash; fi;... sondaki küçük noktalı virgülleri fark etmeyecektir, yani: sonra .bashve fi.
Emmanuel Mahuni

1
Bunu bir zshkullanıcıdan benimle paylaşılan bir senaryoda aldım . İlki ne içinde çalışıyor zshama shne de değil bash. Keşke 4 kişi olsaydım bu 4 olumlu oyu verebilseydim
Davos

44

Ayrıca bir ifcümlede yanlış sözdizimini kullanarak bu hata mesajını aldım

  • else if (sözdizimi hatası: beklenmeyen dosya sonu)
  • elif (doğru sözdizimi)

işe yarayana kadar bit yorumlayarak hata ayıkladım


Çok teşekkür ederim .. birisi lütfen bu adama madalya verin
Happiehappie

21

kapatılmamış bir if => fi cümlesi de bunu yükseltecektir

ipucu: betiğiniz çok büyükse hata ayıklamak için tuzağı kullanın ...

Örneğin

set -x
trap read debug

1
"Fi" yi kesinlikle unutmuşum! Teşekkürler :) Eğer yapabiliyorsanız, herkesin yararı için, tuzağı kullanma ipucunuzu biraz detaylandırın.
Carles Alcolea

3
gecikme için özür dilerim dostum. 'tuzak' komutu, her satırdan sonra esasen keserek komut dosyalarınızda hata ayıklamanın bir yoludur. daha kapsamlı bir tartışma burada: stackoverflow.com/questions/9080431/…
theRiley

1
Bu çok faydalı oldu. unexpected end of fileHatanın fi, vurulduğu anda ortaya çıkacağını unutmayın .
Stephane B.

8

Bu yanıtı StackOverflow'daki bu benzer sorundan aldım

Dosyayı Vim'de açın ve deneyin

:set fileformat=unix

Eh satırı sonlarını unix sonlarına dönüştürün ve sorunun çözülüp çözülmediğine bakın. Vim'de düzenleme yapıyorsanız, şu komutu girin: set fileformat = unix ve dosyayı kaydedin. Notepad ++ veya Atom gibi diğer bazı editörler satır sonlarını dönüştürme yeteneğine sahiptir.

Teşekkürler @lemongrassnginger


Bunlar dos2unix, kabul edilen yanıtın önerdiği şekilde yapmanın alternatif yollarıdır .
ulidtko

7

cygwin'de ihtiyacım olan: -

 export SHELLOPTS
 set -o igncr

.bash_profile içinde. Bu şekilde unix2dos'u çalıştırmama gerek kalmadı


6

Bu yüzden bu yazıyı buldum ve cevaplar bana yardımcı olmadı ama neden bana hatayı verdiğini anlayabildim. sahiptim

cat > temp.txt < EOF
some content
EOF

Sorun, yukarıdaki kodu bir işlevde olacak şekilde kopyalayıp yanlışlıkla kod sekmesine koymamdı. Son EOF'nin sekmeli olmadığından emin olmanız gerekir.


1
Bu tam olarak benim davamdı. EOFDört boşluk girmiştim ve bash bu yüzden ayrıştırmadı. Boşlukların kaldırılması sorunu çözdü.
aexl

6

Tek satıra "if - fi" ifadesini yazdığımda sorun yaşadım:

if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fi

Çok satırlı yazmak sorunumu çözdü:

if [ -f ~/.git-completion.bash ]; then 
    . ~/.git-completion.bash
 fi

3

Bu benim için parens kullanarak bir işlevi çağırmaya çalışırken oluyordu, örn.

run() {
  echo hello
}

run()

olmalı:

run() {
  echo hello
}

run

3

Bir işlev tanımındaki kapanış ayracının eksik olması, keşfettiğim gibi bu hataya neden olacaktır.

function whoIsAnIidiot() {
    echo "you are for forgetting the closing brace just below this line !"

Tabii ki böyle olmalı ...

function whoIsAnIidiot() {
    echo "not you for sure"
}

2

PENCERELER İÇİN:

Benim durumumda, Windows işletim sisteminde çalışıyordum ve autoconf'u çalıştırırken aynı hatayı aldım.

  • Sadece configure.ac dosyasını NOTEPAD ++ IDE ile açıyorum .
  • Daha sonra EOL dönüşümlü dosyayı Windows'a (CR LF) aşağıdaki gibi dönüştürdüm :

    DÜZENLE -> EOL DÖNÜŞÜMÜ -> WINDOWS (CR LF)


1

Kodunuzu kesip bir dosyaya yapıştırabildim ve düzgün çalıştı. Bunu böyle yürütürseniz, çalışmalıdır:

"File.sh" dosyanız:

#!/bin/bash
# june 2011

if [ $# -lt 3 -o $# -gt 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

Komuta:

$ ./file.sh arg1 arg2 arg3

"File.sh" dosyasının çalıştırılabilir olması gerektiğini unutmayın:

$ chmod +x file.sh

Nasıl girdi yaptığınıza dair bu hatayı alıyor olabilirsiniz (boru, havuç vb.). Koşulu ikiye bölmeyi de deneyebilirsiniz:

if [ $# -lt 3 ] || [ $# -gt 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

Veya bashkullandığınız için yerleşik sözdizimini kullanabilirsiniz:

if [[ $# -lt 3 || $# -gt 3 ]]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

Ve son olarak, elbette sadece 3 argüman verilip verilmediğini kontrol edebilirsiniz (temiz, POSIX kabuk uyumluluğunu korur):

if [ $# -ne 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

hala aynı hatayı alıyorum. Kodun nerede yanlış gittiğinden tam olarak emin değilim
markcruz

tuhaf, kodunuzu kestim ve yapıştırdım ve beklendiği gibi çalıştı. başka hata çıktısı var mı? çoğu zaman bash bir satır numarasını listeleyecektir. ayrıca, hangi sistemi çalıştırıyorsunuz? (Linux, MacOS, BSD, dağıtım, vb.)
aaronstacy

1

Benim durumumda, \aşağıdaki gibi bir fazlalık var :

function foo() {
    python tools/run_net.py \
                           --cfg configs/Kinetics/X3D_8x8_R50.yaml \
                           NUM_GPUS 1 \
                           TRAIN.BATCH_SIZE 8 \
                           SOLVER.BASE_LR 0.0125 \
                           DATA.PATH_TO_DATA_DIR ./afs/kinetics400 \
                           DATA.PATH_PREFIX  ./afs/kinetics400  \  # Error
}

Orada DEĞİL bir \sonundaDATA.PATH_PREFIX ./afs/kinetics400


0

Ben sadece örneğinizi kesip bir dosyaya yapıştırdım; bash altında iyi çalıştı. Bununla ilgili herhangi bir sorun görmüyorum.

İyi bir ölçü için, bir satırsonu ile bittiğinden emin olmak isteyebilirsiniz, ancak bash umursamamalıdır. (Benim için son satırsonu ile ve olmadan çalışır.)

Dosyaya yanlışlıkla bir kontrol karakteri yerleştirdiyseniz bazen garip hatalar görürsünüz. Kısa bir betik olduğu için, sorunuzdan StackOverflow'a yapıştırarak veya sadece yeniden yazarak yeni bir betik oluşturmayı deneyin.

Hangi bash sürümünü kullanıyorsunuz? ( bash --version)

İyi şanslar!


0

.Sh dosyasının bulunduğu dizinin adında boşluk karakteri olmadığından emin olun. Örneğin: 'Yeni Klasör' adlı bir klasörde ise, bahsettiğiniz hatayla karşılaşmanız muhtemel olduğunu söyleyin. Bunun yerine, 'New_Folder' olarak adlandırın. Umarım bu yardımcı olur.


0

Görünüşe göre, betiğinizin son satırında yeni satır olmadığında kabuğun bazı sürümleri de bu mesajı verebilir.


0

Ubuntu'da:

$ gedit ~/.profile

Sonra File -> Save asve şu şekilde ayarlayın end line:Unix/Linux



0

MacOS kullanan kişiler için:

Windows formatında bir dosya aldıysanız ve MacOS'ta çalıştırmak istiyorsanız ve bu hatayı görüyorsanız, bu komutları çalıştırın.

brew install dos2unix
sh <file.sh>
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.