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


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.