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.


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.


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

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)


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.


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.


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.


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

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

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

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

-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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.