bash: Substituição ruim

148
#!/bin/bash

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

Este script bash me dá erro de substituição incorreta no Ubuntu. Qualquer ajuda será muito apreciada.

Arindam Choudhury
fonte
Está funcionando bem para mim. O que você está tentando realizar?
fedorqui 'Então pare de prejudicar'
Estou tentando dividir o nome do trabalho em dois: job_201312161447 e 0003. Está dando esse erro apenas quando estou tentando executá-lo no ubuntu.
Arindam Choudhury
Mmmm estranho. E se você usar cut? cut -d_ -f1,2 <<< "$jobname"e cut -d_ -f3 <<< "$jobname"faça-o
fedorqui 'Então pare de prejudicar'
obrigado. mas por que jobname_pre = $ {jobname: 0: 16} deu erro
Arindam Choudhury
1
@ Bludger você está certo, vejo que, se o fizer sh script.sh, recebe um erro de "Substituição incorreta".
fedorqui 'Então, pare de prejudicar'

Respostas:

200

O shell padrão ( /bin/sh) no Ubuntu aponta para dash, não bash.

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

Portanto, se você chmod +x your_script_file.she depois executá-lo com ./your_script_file.sh, ou se executá-lo bash your_script_file.sh, deve funcionar bem.

sh your_script_file.shExecutá- lo com não funcionará porque a linha hashbang será ignorada e o script será interpretado por dash, o que não suporta essa sintaxe de substituição de cadeia.

Vanni Totaro
fonte
2
Ele está usando /bin/bashpara que sua resposta não se encaixe ?! Onde você lê que ele está usando /bin/shou sh script.sh?
Daniel W.
4
@ DanFromGermany porque essa é a única razão para esse erro, ou seja, ele está executando o script de uma maneira que não considera o hashbang, e essa sintaxe do bash não é suportada por outro shell (provavelmente traço). As perguntas nem sempre contêm todos os detalhes necessários, e devemos juntar os pontos ... de qualquer maneira, fique à vontade para votar em minha resposta.
Vanni Totaro
2
Eu não preciso votar. Tenho a mesma mensagem de erro bad substitutione só estou tentando coletar informações, mas esta pergunta não ajuda porque tem poucas informações.
Daniel W.
2
@ DanFromGermany, você pode tentar postar sua própria pergunta, talvez não seja exatamente o mesmo problema.
Vanni Totaro / 01/15
69

Eu tive o mesmo problema. Verifique se o seu script não possui

#!/bin/sh 

no topo do seu script. Em vez disso, você deve adicionar

#!/bin/bash
Convidado
fonte
5
Eu usei #!bin/bashe sh script.sh, ainda me deu a mensagem de erro. Então ./script.shfunciona.
whyisyoung
Se seu arquivo estiver faltando um shebang na parte superior, a adição #!/bin/bashtambém corrigirá a substituição incorreta .
21316 Jamie
1
@whyisyoung sua variável pode ter um ponto (.) no nome. Dá má subst. erro.
User13107
4
@whyisyoung a #!linha é usada somente quando você executa seu script diretamente. Se você usar sh script.sha linha é completamente ignorada.
precisa saber é o seguinte
35

Para outras pessoas que chegam aqui, essa mensagem exata também será exibida ao usar a sintaxe da variável env para comandos, por exemplo, em ${which sh}vez da correta$(which sh)

Nacho Coloma
fonte
21

Sua sintaxe de script é válida e válida.

Possíveis causas da falha:

  1. Você bashnão é realmente bash, mas kshou algum outro shell que não entende a substituição de parâmetros do bash. Porque seu script parece bem e funciona com o bash. Faça ls -l /bin/bashe verifique se realmente é o bash e não está vinculado a nenhum outro shell.

  2. Se você possui o bash no seu sistema, pode estar executando o script da maneira errada, como: ksh script.shou sh script.sh(e seu shell padrão não é o bash). Desde que você tem shebang adequado, se você tem bash ./script.shou bash ./script.shdeve ficar bem.

PP
fonte
7
Eu ficaria surpreso se /bin/bash(não /bin/sh) alguma vez estivesse vinculado a um shell diferente.
chepner
O ksh é realmente o local de origem da maioria das extensões de sintaxe do bash; ele certamente tem a sintaxe expansão parâmetro específico em questão. Eu não sugeriria chamá-lo como um invólucro improvável de ser capaz.
Charles Duffy
7

Tente executar o script explicitamente usando o comando bash, em vez de apenas executá-lo como executável.

Ponto azul pálido
fonte
3
Um bom. Seria útil adicionar um exemplo de saída para torná-lo mais claro, usando sh scripte bash script... minha sugestão :)
fedorqui 'SO stop harming'
4

Além disso, verifique se você não possui uma string vazia para a primeira linha do seu script.

ou seja, verifique se #!/bin/bashé a primeira linha do seu script.

feiticeiro
fonte
3

Não é relevante para o seu exemplo, mas você também pode obter o Bad substitutionerro no Bash para qualquer sintaxe de substituição que o Bash não reconheça. Isto pode ser:

  • Espaço em branco disperso. Por exemplobash -c '${x }'
  • Um erro de digitação. Por exemplobash -c '${x;-}'
  • Um recurso que foi adicionado em uma versão posterior do Bash. Por exemplo, bash -c '${x@Q}'antes do Bash 4.4.

Se você tiver várias substituições na mesma expressão, o Bash pode não ser muito útil para identificar a expressão problemática. Por exemplo:

$ bash -c '"${x } multiline string
$y"'
bash: line 1: ${x } multiline string
$y: bad substitution
Daniel Darabos
fonte
2
Este é o primeiro sucesso, Bad substitutionentão pensei em incluir o caso em que nos deparamos. (Estava @Qno Bash 4.3 escondido em uma longa expressão de várias linhas.)
Daniel Darabos
2
Este foi o meu problema ao executar o Bash 3.x no mac
coloradocolby
2
Prooflink sobre a inclusão@Q em bash-4.4.
x-yuri
2

Ambos - bash ou dash - funcionam, mas a sintaxe precisa ser:

FILENAME=/my/complex/path/name.ext
NEWNAME=${FILENAME%ext}new
Hagen
fonte
1
Essa é uma operação completamente diferente. Além disso, como o OP seguia boas práticas usando nomes de variáveis ​​em minúsculas (consulte pubs.opengroup.org/onlinepubs/9699919799/basedefs/… - nomes em maiúsculas são usados ​​para variáveis ​​com significado para o SO ou shell; nomes em minúsculas são reservado para uso do aplicativo), ele deve fazer o mesmo.
Charles Duffy
0

Parece que "+ x" causa problemas:

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
Andrew Knutsen
fonte
0

Eu estava adicionando um cifrão duas vezes em uma expressão com chaves no bash:

cp -r $PROJECT_NAME ${$PROJECT_NAME}2

ao invés de

cp -r $PROJECT_NAME ${PROJECT_NAME}2
sashoalm
fonte
-1

Eu descobri que esse problema é causado pela resposta marcada ou você tem uma linha ou espaço antes da declaração do bash

Ahmed Oladele
fonte