bash:Bad Substitution


148
#!/bin/bash

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

このbashスクリプトは、Ubuntuでの悪い置換エラーを私に与えます。どんな助けも高く評価されます。


私には問題なく動いています。あなたは何を成し遂げようとしているのですか?
fedorqui 'SO stop harming' 2013

ジョブ名を2つに分割しようとしています:job_201312161447と0003。ubuntuでこれを実行しようとしたときにのみ、このエラーが発生します。
Arindam Choudhury

うーんおかしい。使用するとどうなりますcutか?cut -d_ -f1,2 <<< "$jobname"そしてcut -d_ -f3 <<< "$jobname"それを作る
fedorqui 'SO stop harming' 13/12/16

ありがとう。しかし、jobname_pre = $ {jobname:0:16}がエラーになった理由
Arindam Choudhury

1
@bludger正解です。そうするとsh script.sh、「Bad Substitution 」エラーが表示されます。
fedorqui 'SO stop harming' 2013

回答:


200

/bin/shUbuntuの下のデフォルトのシェル()はdash、ではなくを指していbashます。

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/shsh script.sh
Daniel W.

4
@DanFromGermanyは、それがそのエラーの唯一の理由です。つまり、彼はハッシュバングを考慮しない方法でスクリプトを実行しており、その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

ファイルの上部にシバンが欠落している場合、追加#!/bin/bashすると不良置換も修正されます。
ジェイミー

1
@whyisyoung変数の名前にドット(。)が含まれている可能性があります。それは悪い助かります。エラー。
user13107

4
@whyisyoungこの#!行は、スクリプトを直接実行する場合にのみ使用されます。sh script.sh行を使用すると、完全に無視されます。
bfontaine 2018年

35

他の人がここに到着した場合、コマンドにenv変数の構文を使用する${which sh}と、正しいメッセージの代わりに、この正確なメッセージが表示されます。$(which sh)


21

スクリプト構文は有効なbashであり、優れています。

失敗の考えられる原因:

  1. あなたbashは本当にbash kshではありませんが、bashのパラメータ置換を理解しない他のシェルです。スクリプトが正常に見え、bashで動作するためです。ls -l /bin/bash実際にbashであり、他のシェルにシンボリックリンクされていないことを確認してください。

  2. システムにbashがある場合は、次のようにスクリプトを間違った方法で実行している可能性があります(ksh script.shまたはsh script.shデフォルトのシェルはbashではありません)。あなたが適切なシバンを持っているので、あなたがbashを持っている./script.shbash ./script.sh、大丈夫でなければなりません。


7
/bin/bash(ではなく/bin/sh)別のシェルにリンクされていたとしたら、私は驚くでしょう。
chepner 2013

kshは、実際にはbashの構文拡張機能のほとんどの元です。それは確かに問題の特定のパラメータ拡張構文を持っています。可能性が低いシェルとしてそれを呼び出すことを提案する傾向はありません。
Charles Duffy

7

実行可能ファイルとして実行するのではなく、bashコマンドを使用してスクリプトを明示的に実行してみてください。


3
いいね。を使用してsh script、より明確にするためにいくつかのサンプル出力を追加すると役立ちます。そしてbash script...私の提案:)
fedorqui 'SO stop harming'

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
これはMacでBash 3.xを実行しているときの私の問題でした
coloradocolby

2
@Qに追加されることに関する証明リンクbash-4.4
x-yuri

2

両方-bashまたはdash-機能しますが、構文は次のようにする必要があります。

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

1
それは完全に異なる操作です。また、OPは小文字の変数名を使用して優れた慣行に従っていたため(pubs.opengroup.org/onlinepubs/9699919799/basedefs/…を参照)-OSまたはシェルにとって意味のある変数には大文字の名前が使用されます。小文字の名前はアプリケーションで使用するために予約されています)、同様に行う必要があります。
Charles Duffy

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

私はbashで中かっこを使用して式にドル記号を2回追加していました。

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.