bash: mala sustitución

148
#!/bin/bash

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

Este script bash me da un error de sustitución incorrecto en Ubuntu. Cualquier ayuda será muy apreciada.

Arindam Choudhury
fuente
Me está funcionando bien. ¿Qué estás tratando de lograr?
fedorqui 'SO deja de dañar'
Estoy tratando de dividir el nombre del trabajo en dos: job_201312161447 y 0003. Da este error solo cuando intento ejecutar esto en ubuntu.
Arindam Choudhury
Mmmm extraño. ¿Qué pasa si lo usas cut? cut -d_ -f1,2 <<< "$jobname"y cut -d_ -f3 <<< "$jobname"hacerlo
fedorqui 'así que deja de hacer daño'
Gracias. pero por qué jobname_pre = $ {jobname: 0: 16} dio error
Arindam Choudhury
1
@bludger tienes razón, veo que si lo haces sh script.sh, aparece un error de "Mala sustitución".
fedorqui 'SO dejar de dañar'

Respuestas:

200

El shell predeterminado ( /bin/sh) en Ubuntu apunta a dash, no bash.

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

Entonces, si usted chmod +x your_script_file.shy luego lo ejecuta ./your_script_file.sh, o si lo ejecuta bash your_script_file.sh, debería funcionar bien.

Ejecutarlo sh your_script_file.shno funcionará porque la línea hashbang se ignorará y el script será interpretado por dash, lo que no admite esa sintaxis de sustitución de cadenas.

Vanni Totaro
fuente
2
¿Lo está usando /bin/bashpara que su respuesta no encaje? ¿Dónde lees que está usando /bin/sho sh script.sh?
Daniel W.
44
@DanFromGermany porque esa es la única razón de ese error, es decir, está ejecutando el script de una manera que no considera el hashbang, y esa sintaxis bash no es compatible con algún otro shell (probablemente guión). Las preguntas no siempre contienen todos los detalles necesarios, y debemos unirnos a los puntos ... de todos modos, siéntase libre de rechazar mi respuesta.
Vanni Totaro
2
No necesito hacer un voto negativo. Tengo el mismo mensaje de error bad substitutiony solo estoy tratando de recopilar información, pero esta pregunta no ayuda porque tiene muy poca información.
Daniel W.
2
@DanFromGermany, puedes intentar publicar tu propia pregunta, tal vez no sea exactamente el mismo problema.
Vanni Totaro
69

Yo tuve el mismo problema. Asegúrese de que su guión no tenga

#!/bin/sh 

en la parte superior de tu guión. En cambio, deberías agregar

#!/bin/bash
Invitado
fuente
55
Solía #!bin/bashy sh script.sh, todavía me dio el mensaje de error. Entonces ./script.shfunciona.
whyisyoung
Si a su archivo le falta un shebang en la parte superior, la adición #!/bin/bashtambién reparará la sustitución incorrecta .
Jamie
1
@whyisyoung su variable podría tener un punto (.) en su nombre. Da mala subst. error.
user13107
44
@whyisyoung la #!línea se usa solo cuando ejecuta su script directamente. Si usa sh script.shla línea se ignora por completo.
bfontaine
35

Para otros que lleguen aquí, este mensaje exacto también aparecerá cuando se use la sintaxis de la variable env para los comandos, por ejemplo, en ${which sh}lugar de la correcta$(which sh)

Nacho Coloma
fuente
21

La sintaxis de su script es válida bash y buena.

Posibles causas de la falla:

  1. Your bashno es realmente bash pero ksho algún otro shell que no comprende la sustitución de parámetros de bash. Porque tu script se ve bien y funciona con bash. Haga ls -l /bin/bashy compruebe que sea realmente bash y no esté vinculado a ningún otro shell.

  2. Si tiene bash en su sistema, entonces puede estar ejecutando su script de manera incorrecta como: ksh script.sho sh script.sh(y su shell predeterminado no es bash). Ya que tienes un shebang adecuado, si tienes bash ./script.sho bash ./script.shdeberías estar bien.

PÁGINAS
fuente
77
Me sorprendería si /bin/bash(no /bin/sh) alguna vez estuvieran vinculados a un shell diferente.
chepner
ksh es en realidad de donde se originó la mayoría de las extensiones de sintaxis de bash; que sin duda tiene la sintaxis expansión de parámetro específico en cuestión. No solía sugerir llamarlo como un shell que probablemente no sea capaz.
Charles Duffy
7

Intente ejecutar el script explícitamente usando el comando bash en lugar de solo ejecutarlo como ejecutable.

Pálido punto azul
fuente
3
Bueno Sería útil agregar algunos resultados de muestra para hacerlo más claro, usando sh scripty bash script... mi sugerencia :)
fedorqui 'SO deja de dañar'
4

Además, asegúrese de no tener una cadena vacía para la primera línea de su secuencia de comandos.

es decir, asegúrese de que #!/bin/bashsea ​​la primera línea de su secuencia de comandos.

wizurd
fuente
3

No es relevante para su ejemplo, pero también puede obtener el Bad substitutionerror en Bash para cualquier sintaxis de sustitución que Bash no reconozca. Esto podría ser:

  • Espacio en blanco perdido. P.ejbash -c '${x }'
  • Un error. P.ejbash -c '${x;-}'
  • Una característica que se agregó en una versión posterior de Bash. Por ejemplo, bash -c '${x@Q}'antes de Bash 4.4.

Si tiene múltiples sustituciones en la misma expresión, Bash puede no ser muy útil para identificar la expresión problemática. P.ej:

$ bash -c '"${x } multiline string
$y"'
bash: line 1: ${x } multiline string
$y: bad substitution
Daniel Darabos
fuente
2
Este es el primer éxito, Bad substitutionasí que pensé en incluir el caso con el que nos encontramos. (Estaba @Qen Bash 4.3 escondiéndose en una larga expresión de varias líneas.)
Daniel Darabos
2
Este fue mi problema al ejecutar Bash 3.x en mac
coloradocolby
2
Prooflink con respecto a @Qser agregado en bash-4.4.
x-yuri
2

Ambos, bash o dash, funcionan, pero la sintaxis debe ser:

FILENAME=/my/complex/path/name.ext
NEWNAME=${FILENAME%ext}new
Hagen
fuente
1
Esa es una operación completamente diferente. Además, dado que el OP seguía las buenas prácticas al usar nombres de variables en minúsculas (ver pubs.opengroup.org/onlinepubs/9699919799/basedefs/… - los nombres en mayúsculas se usan para variables con significado para el sistema operativo o el shell; los nombres en minúsculas son reservado para el uso de la aplicación), corresponde hacer lo mismo.
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
fuente
0

Estaba agregando un signo de dólar dos veces en una expresión con llaves en bash:

cp -r $PROJECT_NAME ${$PROJECT_NAME}2

en vez de

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

He descubierto que este problema es causado por la respuesta marcada o tiene una línea o espacio antes de la declaración de bash

Ahmed Oladele
fuente