ข้อผิดพลาดทางไวยากรณ์ใกล้กับโทเค็นที่ไม่คาดคิด `('


15

เมื่อฉันใช้รหัสด้านล่างใน terminal SSH สำหรับ CentOS มันทำงานได้ดี:

paste <(printf "%s\n" "TOP")

แต่ถ้าฉันวางโค้ดบรรทัดเดียวกันในเชลล์สคริปต์ (test.sh) และรันเชลล์สคริปต์จากเทอร์มินัลมันจะพ่นข้อผิดพลาดเช่นนี้

./test.sh: line 30: syntax error near unexpected token ('   
./test.sh: line 30:     paste <(printf "%s\n" "TOP")

ฉันจะแก้ไขปัญหานี้ได้อย่างไร


วิธีว่าคุณกำลังเรียกใช้มันได้หรือไม่ อะไร '#!' บรรทัด (ถ้ามี) เริ่มสคริปต์ของคุณ? ดูเหมือนว่าคุณกำลังเรียกใช้ตัวแปลเชลล์ที่ไม่รองรับไวยากรณ์นั้น (เช่นdashแทนที่จะเป็นbash)
ขับเหล็ก

ฉันมี#!/bin/shที่ด้านบน ฉันทำตามbash test.shแต่มันก็ไม่ได้ผลเหมือนกัน
NecNecco

bashในโหมด POSIX ไม่สนับสนุนไวยากรณ์นั้น (เมื่อเรียกด้วย--posixหรือเป็น/bin/sh) #!/bin/bashใช้
จอร์แดน

@NecNecco: คุณมีการPOSIXLY_CORRECTตั้งค่าตัวแปรเมื่อคุณเริ่มbash?
cuonglm

@ jordanm เปลี่ยนไป#!/bin/bashที่ด้านบนแก้ไขปัญหา
NecNecco

คำตอบ:


23

กระบวนการทดแทนไม่ได้ระบุโดย POSIX จึงไม่สนับสนุน POSIX เปลือกมันเพียงเปลือกบางชอบbash, zsh, ksh88, ksh93สนับสนุน

ในCentosระบบ/bin/shเป็น symlink /bin/bashไป เมื่อbashถูกเรียกด้วยชื่อsh, bashเข้าสู่โหมด POSIX ( ทุบตีไฟล์ Startup - เรียกด้วยชื่อดวลจุดโทษ ) ในโหมด posix process substitutionไม่รองรับทำให้เกิดข้อผิดพลาดทางไวยากรณ์

สคริปต์ควรจะทำงานถ้าคุณโทรโดยตรงbash bash test.shถ้าไม่ใช่อาจbashเข้าสู่โหมด posix สิ่งนี้อาจเกิดขึ้นได้หากคุณเริ่มต้นbashด้วย--posixอาร์กิวเมนต์หรือPOSIXLY_CORRECTตั้งค่าตัวแปรเมื่อbashเริ่มต้น

$ bash --posix test.sh 
test.sh: line 54: syntax error near unexpected token `('
test.sh: line 54: `paste <(printf "%s\n" "TOP")'

$ POSIXLY_CORRECT=1 bash test.sh 
test.sh: line 54: syntax error near unexpected token `('
test.sh: line 54: `paste <(printf "%s\n" "TOP")

หรือbashถูกสร้างขึ้นด้วย--enable-strict-posix-defaultตัวเลือก

ที่นี่คุณไม่ต้องการทดแทนกระบวนการคุณสามารถใช้ท่อเปลือกมาตรฐานได้:

printf "%s\n" "TOP" | paste -

-เป็นวิธีมาตรฐานในการบอกpasteให้อ่านข้อมูลจาก stdin ด้วยpasteการใช้งานบางอย่างคุณสามารถละเว้นได้แม้ว่าจะไม่ได้มาตรฐาน

โดยที่มันจะมีประโยชน์คือเมื่อวางเอาต์พุตของคำสั่งมากกว่าหนึ่งคำสั่งเช่น:

paste <(cmd1) <(cmd2)

บนระบบที่รองรับ/dev/fd/nซึ่งสามารถทำได้shด้วย:

{ cmd1 4<&- | { cmd2 3<&- | paste /dev/fd/3 -; } 3<&0 <&4 4<&-; } 4<&0

(มันคือสิ่งที่<(...)เกิดขึ้นภายใน)


2

นี่เป็นวิธีแก้ปัญหาอื่น แทนที่จะรันคำสั่งให้รัน bash และส่งคำสั่งไปยัง bash โดยใช้ -c:

bash -c 'paste <(printf "%s\n" "TOP")'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.