bash: การเปลี่ยนตัวไม่ดี


148
#!/bin/bash

jobname="job_201312161447_0003"
jobname_pre=${jobname:0:16}
jobname_post=${jobname:17}

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


มันทำงานได้ดีสำหรับฉัน คุณพยายามทำอะไรให้สำเร็จ
fedorqui 'ดังนั้นหยุดการทำร้าย'

ฉันกำลังพยายามแบ่งชื่องานเป็นสอง: job_201312161447 และ 0003 มันให้ข้อผิดพลาดนี้เฉพาะเมื่อฉันพยายามเรียกใช้งานบน Ubuntu
Arindam Choudhury

อืมมมแปลก เกิดอะไรขึ้นถ้าคุณใช้cut? cut -d_ -f1,2 <<< "$jobname"และcut -d_ -f3 <<< "$jobname"ทำให้มัน
fedorqui 'ดังนั้นหยุดการทำร้าย'

ขอบคุณ แต่ทำไม jobname_pre = $ {jobname: 0: 16} ให้ข้อผิดพลาด
Arindam Choudhury

1
@ ตัวบล็อกของคุณถูกต้องฉันเห็นว่าถ้าคุณทำเช่นsh script.shนั้นจะได้รับข้อผิดพลาด "การแทนที่ไม่ถูกต้อง"
fedorqui 'ดังนั้นหยุดการทำร้าย'

คำตอบ:


200

เปลือกต้น ( /bin/sh) ภายใต้อูบุนตูชี้ไปไม่ได้dashbash

me@pc:~$ readlink -f $(which sh)
/bin/dash

ดังนั้นหากคุณchmod +x your_script_file.shแล้วเรียกใช้ด้วย./your_script_file.shหรือถ้าคุณเรียกใช้ด้วยbash your_script_file.shมันควรจะทำงานได้ดี

การรันด้วยsh your_script_file.shจะไม่ทำงานเนื่องจากบรรทัด hashbang จะถูกละเว้นและสคริปต์จะถูกตีความโดยdashซึ่งไม่สนับสนุนไวยากรณ์การแทนที่สตริงนั้น


2
เขากำลังใช้/bin/bashเพื่อให้คำตอบของคุณไม่พอดี?! คุณอ่านว่าเขาใช้/bin/shหรือsh script.shที่ไหน
Daniel W.

4
@DanFromGermany เพราะนั่นเป็นเหตุผลเดียวที่ทำให้เกิดข้อผิดพลาดนั่นคือเขากำลังเรียกใช้สคริปต์ในลักษณะที่ไม่พิจารณา hashbang และไวยากรณ์ bash นั้นไม่ได้รับการสนับสนุนจากเชลล์อื่น ๆ (อาจเป็นขีดกลาง) คำถามไม่ได้มีรายละเอียดที่จำเป็นทั้งหมดอยู่เสมอและเราจะต้องเข้าร่วมกับจุดต่างๆ ...
Vanni Totaro

2
ฉันไม่จำเป็นต้องลงคะแนน ฉันมีข้อความแสดงข้อผิดพลาดเหมือนกันbad substitutionและฉันพยายามรวบรวมข้อมูล แต่คำถามนี้ไม่ได้ช่วยเพราะมีข้อมูลน้อยเกินไป
Daniel W.

2
@DanFromGermany คุณสามารถลองโพสต์คำถามของคุณเองอาจจะไม่ใช่ปัญหาเดียวกัน
Vanni Totaro

69

ผมมีปัญหาเหมือนกัน. ตรวจสอบให้แน่ใจว่าสคริปต์ของคุณไม่มี

#!/bin/sh 

ที่ด้านบนของสคริปต์ของคุณ แต่คุณควรเพิ่ม

#!/bin/bash

5
ฉันใช้#!bin/bashและsh script.shมันก็ยังให้ข้อความข้อผิดพลาด จากนั้นได้./script.shผล
Whyisyoung

หากไฟล์ของคุณจะหายไป shebang ที่ด้านบนเพิ่ม#!/bin/bashนอกจากนี้ยังจะแก้ไขเปลี่ยนตัว Bad
เจมี่

1
@whyisyoung ตัวแปรของคุณอาจมีจุด (.) อยู่ในชื่อ มันให้ subst ที่ไม่ดี ความผิดพลาด
user13107

4
@whyisyoung #!บรรทัดนี้ใช้เฉพาะเมื่อคุณเรียกใช้งานสคริปต์โดยตรง หากคุณใช้sh script.shสายจะถูกละเว้นอย่างสมบูรณ์
bfontaine

35

สำหรับคนอื่นที่มาถึงที่นี่ข้อความตรงนี้จะปรากฏขึ้นเมื่อใช้ไวยากรณ์ตัวแปร env สำหรับคำสั่งตัวอย่างเช่น${which sh}แทนที่จะเป็นคำที่ถูกต้อง$(which sh)


21

ไวยากรณ์ของสคริปต์ของคุณคือทุบตีที่ถูกต้องและดี

สาเหตุที่เป็นไปได้สำหรับความล้มเหลว:

  1. คุณbashไม่ใช่คนทุบตีจริง ๆkshหรือบางตัวที่ไม่เข้าใจการทดแทนพารามิเตอร์ของ bash เพราะสคริปต์ของคุณดูดีและใช้ได้กับการทุบตี ทำls -l /bin/bashและตรวจสอบว่ามันทุบตีจริงๆและไม่ได้เชื่อมโยงกับเชลล์อื่น ๆ

  2. หากคุณมีทุบตีในระบบของคุณแล้วคุณอาจจะรันสคริปต์ของคุณในทางที่ผิดเช่น: ksh script.shหรือsh script.sh(และเปลือกเริ่มต้นของคุณจะไม่ทุบตี) เนื่องจากคุณมี Shebang ที่เหมาะสมถ้าคุณทุบตี./script.shหรือbash ./script.shควรจะดี


7
ฉันจะแปลกใจถ้า/bin/bash(ไม่/bin/sh) เคยเชื่อมโยงกับเปลือกที่แตกต่างกัน
chepner

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

7

ลองเรียกใช้สคริปต์อย่างชัดเจนโดยใช้คำสั่ง bash แทนที่จะเรียกใช้งานมันเป็นไฟล์ที่เรียกใช้งานได้


3
สิ่งที่ดี. มันจะมีประโยชน์ในการเพิ่มเอาต์พุตตัวอย่างบางส่วนเพื่อให้ชัดเจนยิ่งขึ้นโดยใช้sh scriptและbash script... คำแนะนำของฉัน :)
fedorqui 'ดังนั้นหยุดการทำร้าย'

4

นอกจากนี้ตรวจสอบให้แน่ใจว่าคุณไม่มีสตริงว่างสำหรับบรรทัดแรกของสคริปต์

คือทำให้แน่ใจว่า#!/bin/bashเป็นบรรทัดแรกของสคริปต์ของคุณ


3

ไม่เกี่ยวข้องกับตัวอย่างของคุณ แต่คุณสามารถรับBad substitutionข้อผิดพลาดใน Bash สำหรับไวยากรณ์การแทนที่ใด ๆ ที่ Bash ไม่รู้จัก นี่อาจเป็น:

  • ช่องว่างที่หลงทาง เช่นbash -c '${x }'
  • พิมพ์ผิด เช่นbash -c '${x;-}'
  • คุณลักษณะที่เพิ่มเข้ามาในเวอร์ชัน Bash ในภายหลัง เช่นbash -c '${x@Q}'ก่อน Bash 4.4

หากคุณมีการแทนที่หลายรายการในนิพจน์เดียวกัน Bash อาจไม่เป็นประโยชน์ในการระบุนิพจน์ที่มีปัญหา เช่น:

$ bash -c '"${x } multiline string
$y"'
bash: line 1: ${x } multiline string
$y: bad substitution

2
นี่เป็นเกมแรกที่Bad substitutionฉันคิดว่าฉันจะใส่เคสที่เราพบเจอ (มันอยู่@Qใน Bash 4.3 ซึ่งซ่อนเร้นในหลายบรรทัด)
Daniel Darabos

2
นี่เป็นปัญหาของฉันเมื่อใช้ Bash 3.x บน mac
coloradocolby

2
Prooflinkเกี่ยวกับ@Qการเพิ่มเข้าbash-4.4มา
x-yuri

2

ทั้งสอง - ทุบตีหรือเส้นประ - ทำงาน แต่ไวยากรณ์ต้องเป็น:

FILENAME=/my/complex/path/name.ext
NEWNAME=${FILENAME%ext}new

1
นั่นเป็นการดำเนินการที่แตกต่างอย่างสิ้นเชิง นอกจากนี้เนื่องจาก OP ปฏิบัติตามแนวทางปฏิบัติที่ดีโดยใช้ชื่อตัวแปรตัวพิมพ์เล็ก (ดูpubs.opengroup.org/onlinepubs/9699919799/basedefs/… - ชื่อตัวพิมพ์ใหญ่ใช้สำหรับตัวแปรที่มีความหมายกับ OS หรือเชลล์ชื่อตัวพิมพ์เล็กคือ สงวนไว้สำหรับการใช้งานแอปพลิเคชัน) มันจะทำเช่นเดียวกัน
ชาร์ลส์ดัฟฟี่

0

ดูเหมือนว่า "+ x" ทำให้เกิดปัญหา:

root@raspi1:~# cat > /tmp/btest
#!/bin/bash

jobname="job_201312161447_0003"
jobname_pre=${jobname:0:16}
jobname_post=${jobname:17}
root@raspi1:~# chmod +x /tmp/btest
root@raspi1:~# /tmp/btest
root@raspi1:~# sh -x /tmp/btest
+ jobname=job_201312161447_0003
/tmp/btest: 4: /tmp/btest: Bad substitution

0

ฉันกำลังเพิ่มเครื่องหมายดอลลาร์สองครั้งในการแสดงออกด้วยเครื่องหมายปีกกาในทุบตี:

cp -r $PROJECT_NAME ${$PROJECT_NAME}2

แทน

cp -r $PROJECT_NAME ${PROJECT_NAME}2

-1

ฉันพบว่าปัญหานี้อาจเกิดจากคำตอบที่ทำเครื่องหมายไว้หรือคุณมีเส้นหรือช่องว่างก่อนประกาศ bash

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