ข้อผิดพลาดทางไวยากรณ์ Bash: จุดสิ้นสุดของไฟล์โดยไม่คาดคิด


102

ยกโทษให้ฉันด้วยนี่เป็นสคริปต์ที่เรียบง่ายมากใน Bash นี่คือรหัส:

#!/bin/bash
# june 2011

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

หลังจากเรียกใช้ sh file.sh:

ข้อผิดพลาดทางไวยากรณ์: จุดสิ้นสุดของไฟล์ที่ไม่คาดคิด

คำตอบ:


144

ฉันคิดว่า file.sh ใช้ตัวยุติสาย CRLF

วิ่ง

dos2unix file.sh

จากนั้นปัญหาจะได้รับการแก้ไข

คุณสามารถติดตั้ง dos2unix ใน ubuntu ด้วยสิ่งนี้:

sudo apt-get install dos2unix

อะไรคือสาเหตุของปัญหานี้? ฉันมักจะทำงานบน Windows แต่ต้องถ่ายโอนสคริปต์ไปยังระบบยูนิกซ์
CMCDragonkai

บรรทัดใหม่ใน windows คือ "\ r \ n" ในขณะที่ใน linux คือ "\ n"
clyfish

8
@KeesdeKooter ฉันจะไม่พูดเพียงเพราะมีบางอย่างไม่ได้ผลสำหรับคุณที่คุณควรลงคะแนนเห็นได้ชัดว่ามันใช้ได้กับ 28 upvotes มันไม่ได้ผลสำหรับฉันพอเพียง นั่นเป็นเหตุผลที่ SO อนุญาตให้ตอบคำถามได้หลายข้อเนื่องจากสามารถแก้ปัญหาได้หลายวิธี
Jeff Wilbert

2
การใช้โปรแกรมแก้ไข notepad ++ แก้ไข> การแปลง EOL> รูปแบบ Mac เก่าแก้ไขให้ฉันได้
raktale

หากคุณสามารถแก้ไขไฟล์ bash ของคุณด้วย Notepad ++ ไปที่ Edit-> EOL Conversion-> Macintosh (CR) เปลี่ยนเป็น Macintosh (CR) แม้ว่าคุณจะใช้ Windows OS ก็ตาม
Juniar

133

สิ่งอื่นที่ต้องตรวจสอบ (เพิ่งเกิดขึ้นกับฉัน):

  • ยุติเนื้อหาของฟังก์ชันบรรทัดเดียวด้วยอัฒภาค

กล่าวคือตัวอย่างข้อมูลที่ดูไร้เดียงสานี้จะทำให้เกิดข้อผิดพลาดเดียวกัน:

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

วิธีทำให้ตัวแยกวิเคราะห์ใบ้มีความสุข:

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

3
+1 ยังใช้กับข้อมูลโค้ดที่มีวงเล็บดังนี้: [["$ #" == 1]] && [["$ arg" == [1,2,3,4]]] && printf "% s \ n "" บลา "|| {printf "% s \ n" "blahblah"; การใช้งาน; } ............ โปรดสังเกตว่าอัฒภาคในวงเล็บเหลี่ยมหลังจากเรียกฟังก์ชันที่กำหนดไว้ก่อนหน้านี้ว่า 'การใช้งาน' การลืมนั่นจะทำให้คุณได้รับข้อผิดพลาดทางไวยากรณ์เดียวกัน: eof ที่ไม่คาดคิด
Cbhihe

คุณตอกมัน ที่จริงสิ่งที่ง่ายเป็น;คำสั่งทุกคนจะถูกคาดหวังว่าจะจบลงด้วยการ;ใส่เพื่อที่อย่างเช่นปลาย: if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fiจะผลิตข้อผิดพลาดที่ในขณะที่if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash; fi;จะไม่แจ้งให้ทราบล่วงหน้า ... เล็ก ๆ น้อย ๆ จุดคู่กึ่งที่สิ้นสุดเช่น: หลังและ.bash fi
Emmanuel Mahuni

1
ฉันมีสิ่งนี้ในสคริปต์ที่แบ่งปันกับฉันจากzshผู้ใช้ อดีตทำงานในzshแต่ไม่ได้อยู่ในมิได้sh bashหวังว่าฉันจะเป็น 4 คนเพื่อให้ฉันสามารถให้คะแนน
ดาวอส

44

ฉันเพิ่งได้รับข้อความแสดงข้อผิดพลาดนี้โดยใช้ไวยากรณ์ที่ไม่ถูกต้องในifอนุประโยค

  • else if (ข้อผิดพลาดทางไวยากรณ์: จุดสิ้นสุดของไฟล์ที่ไม่คาดคิด)
  • elif (ไวยากรณ์ที่ถูกต้อง)

ฉันแก้ไขข้อบกพร่องโดยการแสดงความคิดเห็นบิตจนกว่าจะใช้งานได้


ขอบคุณมาก.. ใครก็ได้โปรดให้เหรียญผู้ชายคนนี้
Happiehappie

21

un-closed if => fi clause จะเพิ่มสิ่งนี้เช่นกัน

เคล็ดลับ: ใช้กับดักเพื่อแก้ไขข้อบกพร่องหากสคริปต์ของคุณมีขนาดใหญ่ ...

เช่น

set -x
trap read debug

1
ฉันลืม "ไฟ"! ขอบคุณ :) หากทำได้เพื่อประโยชน์ของทุกคนโปรดอธิบายเกี่ยวกับเคล็ดลับในการใช้กับดัก
Carles Alcolea

3
ขอโทษสำหรับความล่าช้าเพื่อนของฉัน คำสั่ง 'กับดัก' เป็นวิธีการดีบักสคริปต์ของคุณโดยทำลายทุกบรรทัด การอภิปรายที่เต็มรูปแบบอยู่ที่นี่: stackoverflow.com/questions/9080431/…
theRiley

1
นั่นเป็นประโยชน์ขอบคุณมาก โปรดทราบว่าunexpected end of fileข้อผิดพลาดจะเกิดขึ้นทันทีที่fiตี
Stephane B.

8

ฉันได้รับคำตอบนี้จากปัญหาที่คล้ายกันนี้ใน StackOverflow

เปิดไฟล์ใน Vim แล้วลอง

:set fileformat=unix

แปลง eh line endings เป็น unix endings และดูว่าสามารถแก้ปัญหาได้หรือไม่ หากแก้ไขใน Vim ให้ป้อนคำสั่ง set fileformat = unix แล้วบันทึกไฟล์ ตัวแก้ไขอื่น ๆ อีกหลายคนมีความสามารถในการแปลงส่วนท้ายบรรทัดเช่น Notepad ++ หรือ Atom

ขอบคุณ @lemongrassnginger


นี่เป็นเพียงทางเลือกอื่นในการทำdos2unixตามคำแนะนำที่ยอมรับ
ulidtko

7

บน cygwin ฉันต้องการ: -

 export SHELLOPTS
 set -o igncr

ใน. bash_profile วิธีนี้ฉันไม่จำเป็นต้องเรียกใช้ unix2dos


6

ดังนั้นฉันจึงพบโพสต์นี้และคำตอบไม่ได้ช่วยฉัน แต่ฉันสามารถหาสาเหตุที่ทำให้เกิดข้อผิดพลาดได้ ฉันมี

cat > temp.txt < EOF
some content
EOF

ปัญหาคือฉันคัดลอกโค้ดด้านบนเพื่อให้อยู่ในฟังก์ชันและแท็บโค้ดโดยไม่ได้ตั้งใจ ต้องแน่ใจว่าไม่มีแท็บ EOF สุดท้าย


1
นี่เป็นกรณีของฉัน ฉันEOFเยื้องด้วยช่องว่างสี่ช่องและ bash ไม่ได้แยกวิเคราะห์เพราะเหตุนั้น การลบช่องว่างช่วยแก้ปัญหาได้
aexl

6

ฉันมีปัญหาเมื่อเขียนคำสั่ง "if - fi" ในบรรทัดเดียว:

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

การเขียนหลายบรรทัดช่วยแก้ปัญหาของฉัน:

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


3

ไม่มีวงเล็บปีกกาปิดในนิยามฟังก์ชันจะทำให้เกิดข้อผิดพลาดนี้ตามที่ฉันเพิ่งค้นพบ

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

ซึ่งแน่นอนว่าควรเป็นเช่นนี้ ...

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

2

สำหรับ WINDOWS:

ในกรณีของฉันฉันกำลังทำงานบน Windows OS และฉันได้รับข้อผิดพลาดเดียวกันขณะเรียกใช้ autoconf

  • ฉันเพียงแค่เปิดไฟล์config.acด้วยNOTEPAD ++ IDE ของฉัน
  • จากนั้นฉันแปลงไฟล์ด้วยการแปลงEOLเป็นWindows (CR LF)ดังนี้:

    แก้ไข -> แปลง EOL -> WINDOWS (CR LF)


1

ฉันสามารถตัดและวางโค้ดของคุณลงในไฟล์และทำงานได้อย่างถูกต้อง หากคุณดำเนินการเช่นนี้ควรใช้งานได้:

"file.sh" ของคุณ:

#!/bin/bash
# june 2011

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

คำสั่ง:

$ ./file.sh arg1 arg2 arg3

โปรดทราบว่า "file.sh" ต้องสามารถเรียกใช้งานได้:

$ chmod +x file.sh

คุณอาจได้รับข้อผิดพลาด b / c ว่าคุณกำลังป้อนข้อมูลอย่างไร (w / a ไปป์แครอท ฯลฯ ) คุณสามารถลองแบ่งเงื่อนไขออกเป็นสองเงื่อนไข:

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

หรือเนื่องจากคุณกำลังใช้bashคุณสามารถใช้ไวยากรณ์ในตัว:

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

และในที่สุดคุณสามารถตรวจสอบได้ว่ามีการให้ 3 อาร์กิวเมนต์หรือไม่ (สะอาดรักษาความเข้ากันได้ของเชลล์ POSIX)

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

ฉันยังคงได้รับข้อผิดพลาดเดียวกัน ฉันไม่แน่ใจว่ารหัสผิดพลาดตรงไหน
markcruz

แปลกฉันตัดและวางรหัสของคุณและมันก็ทำงานตามที่คาดไว้ มีข้อผิดพลาดเพิ่มเติมหรือไม่? ทุบตีบ่อยครั้งจะแสดงหมายเลขบรรทัด คุณใช้ระบบอะไรอยู่? (Linux, MacOS, BSD, distro ฯลฯ )
aaronstacy

1

ในกรณีของฉันมีสิ่ง\ต่อไปนี้ซ้ำซ้อน:

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
}

นอกจากนี้ไม่\ในตอนท้ายของDATA.PATH_PREFIX ./afs/kinetics400


0

ฉันเพิ่งตัดและวางตัวอย่างของคุณลงในไฟล์ มันวิ่งได้ดีภายใต้การทุบตี ฉันไม่เห็นปัญหาใด ๆ กับมัน

สำหรับมาตรการที่ดีคุณอาจต้องการให้แน่ใจว่ามันลงท้ายด้วยการขึ้นบรรทัดใหม่แม้ว่า bash ก็ไม่ควรสนใจ (มันทำงานสำหรับฉันทั้งที่มีและไม่มีขึ้นบรรทัดใหม่สุดท้าย)

บางครั้งคุณจะเห็นข้อผิดพลาดแปลก ๆ หากคุณฝังอักขระควบคุมลงในไฟล์โดยไม่ได้ตั้งใจ เนื่องจากเป็นสคริปต์สั้น ๆ ให้ลองสร้างสคริปต์ใหม่โดยวางจากคำถามของคุณที่นี่ใน StackOverflow หรือพิมพ์ซ้ำ

คุณใช้ bash รุ่นอะไร? ( bash --version)

โชคดี!


0

ตรวจสอบให้แน่ใจว่าชื่อของไดเร็กทอรีที่มีไฟล์. sh ไม่มีอักขระเว้นวรรค เช่น: สมมติว่าอยู่ในโฟลเดอร์ชื่อ 'โฟลเดอร์ใหม่' คุณจะพบข้อผิดพลาดที่คุณอ้างถึง แต่ตั้งชื่อเป็น "New_Folder" แทน ฉันหวังว่านี่จะช่วยได้.


0

เห็นได้ชัดว่าเชลล์บางเวอร์ชันสามารถส่งข้อความนี้เมื่อบรรทัดสุดท้ายของสคริปต์ของคุณไม่มีการขึ้นบรรทัดใหม่



0

ฉันรู้ว่าฉันมางานปาร์ตี้ช้าเกินไป หวังว่านี่อาจช่วยใครบางคนได้

ตรวจสอบไฟล์. bashrc ของคุณ บางทีเปลี่ยนชื่อหรือย้าย

การอภิปรายที่นี่: ไม่สามารถจัดหาสคริปต์ทุบตีธรรมดาได้


0

สำหรับผู้ที่ใช้ MacOS:

หากคุณได้รับไฟล์ที่มีรูปแบบ Windows และต้องการเรียกใช้บน MacOS และเห็นข้อผิดพลาดนี้ให้เรียกใช้คำสั่งเหล่านี้

brew install dos2unix
sh <file.sh>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.