Баш: плохая замена


148
#!/bin/bash

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

Этот скрипт bash выдает мне ошибку подстановки в Ubuntu. Любая помощь будет высоко оценена.


Это работает нормально для меня. Что вы пытаетесь достичь?
Федорки 'ТАК прекрати вредить'

Я пытаюсь разделить имя задания на два: job_201312161447 и 0003. Это выдает эту ошибку, только когда я пытаюсь запустить это на Ubuntu.
Ариндам Чоудхури

Ммм странно. Что делать, если вы используете cut? cut -d_ -f1,2 <<< "$jobname"и cut -d_ -f3 <<< "$jobname"сделай это
fedorqui 'ТАК ХОТИТЕ вредить'

Спасибо. но почему jobname_pre = $ {jobname: 0: 16} дал ошибку
Ариндам Чоудхури

1
@bludger вы правы, я вижу, что если вы это сделаете, sh script.shон получит ошибку «Плохая замена».
Федорки 'ТАК прекрати вредить'

Ответы:


200

Оболочка по умолчанию ( /bin/sh) в Ubuntu указывает на 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/shили sh script.sh?
Даниэль В.

4
@DanFromGermany, потому что это единственная причина этой ошибки, то есть он запускает скрипт так, что не учитывает hashbang, и этот синтаксис bash не поддерживается какой-либо другой оболочкой (вероятно, dash). Вопросы не всегда содержат всю необходимую информацию, и мы должны присоединиться к точкам ... в любом случае, не стесняйтесь понижать мой ответ.
Ванни Тотаро

2
Мне не нужно понижать голос. У меня такое же сообщение об ошибке, bad substitutionи я просто пытаюсь собрать информацию, но этот вопрос не помогает, потому что в нем слишком мало информации.
Даниэль В.

2
@DanFromGermany вы можете попробовать опубликовать свой вопрос, возможно, это не совсем та же проблема.
Ванни Тотаро

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

35

Для тех, кто прибывает сюда, это точное сообщение также появится при использовании синтаксиса переменной env для команд, например, ${which sh}вместо правильного$(which sh)


21

Синтаксис вашего скрипта правильный bash и хорош.

Возможные причины сбоя:

  1. Вы на bashсамом деле не bash, а kshкакая-то другая оболочка, которая не понимает подстановку параметров bash. Потому что ваш скрипт выглядит нормально и работает с bash. Сделайте ls -l /bin/bashи проверьте, что это действительно bash, а не sym-связанный с какой-либо другой оболочкой.

  2. Если у вас есть bash в вашей системе, то, возможно, вы выполняете свой скрипт неправильно, как: ksh script.shили sh script.sh(и ваша оболочка по умолчанию не bash). Так как у вас есть правильный Шебанг, если у вас есть Bash ./script.shили bash ./script.shдолжно быть в порядке.


7
Я был бы удивлен, если /bin/bash(не /bin/sh) когда-либо были связаны с другой оболочкой.
chepner

ksh на самом деле является источником большинства синтаксических расширений bash; он, безусловно, имеет конкретный синтаксис расширения параметров в вопросе. Я бы не стал называть это оболочкой, которая вряд ли будет способна.
Чарльз Даффи

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, скрывающемся в длинном многострочном выражении.)
Даниэль Дарабос

2
Это была моя проблема при запуске Bash 3.x на Mac
coloradocolby

2
Prooflink о @Qдобавлении в bash-4.4.
х-юрий

2

Оба - bash или dash - работают, но синтаксис должен быть:

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

1
Это совершенно другая операция. Кроме того, поскольку OP следовал передовой практике, используя строчные имена переменных (см. Pubs.opengroup.org/onlinepubs/9699919799/basedefs/… - прописные имена используются для переменных, имеющих значение для ОС или оболочки; строчные имена зарезервировано для использования в приложениях), это необходимо сделать аналогичным образом.
Чарльз Даффи

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:

cp -r $PROJECT_NAME ${$PROJECT_NAME}2

вместо того

cp -r $PROJECT_NAME ${PROJECT_NAME}2

-1

Я обнаружил, что эта проблема вызвана помеченным ответом или у вас есть строка или пробел перед объявлением bash

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.