bash: Погана заміна


148
#!/bin/bash

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

Цей скрипт bash дає мені погану помилку підстановки на Ubuntu. Будь-яка допомога буде високо оцінена.


Мені це добре працює. Що ви намагаєтеся досягти?
— fedorqui 'ТАК перестаньте шкодити'

Я намагаюся розділити ім'я роботи на два: job_201312161447 та 0003. Це давання цієї помилки лише тоді, коли я намагаюся запустити це на ubuntu.
— Arindam Choudhury

Мммм дивно. Що робити, якщо ви використовуєте cut? cut -d_ -f1,2 <<< "$jobname"і cut -d_ -f3 <<< "$jobname"зробити це
— fedorqui 'ТАК перестаньте шкодити'

Дякую. але чому jobname_pre = $ {jobname: 0: 16}
— помилився

1
@bludger ви маєте рацію, я бачу, що якщо ви зробите sh script.shце, ви отримаєте помилку "Погана заміна".
— fedorqui 'ТАК перестаньте шкодити'

Відповіді:


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не вийде, оскільки рядок хешбангу буде проігноровано, а сценарій буде інтерпретований dash, який не підтримує синтаксис підстановки рядків.


2
Він використовує, /bin/bashщоб ваша відповідь не підходила ?! Де ви читаєте, що він використовує /bin/shабо sh script.sh?
— Даніель В.

4
@DanFromGermany, тому що це єдина причина цієї помилки, тобто він запускає скрипт таким чином, що не враховує хешбанг, і що синтаксис bash не підтримується якоюсь іншою оболонкою (можливо, тире). Запитання не завжди містять усі необхідні деталі, і ми повинні приєднатися до крапок ... все одно не соромтеся оскаржувати мою відповідь.
— Ванні Тотаро

2
Мені не потрібно звертати увагу. У мене те саме повідомлення про помилку, bad substitutionі я просто намагаюся зібрати інформацію, але це питання не допомагає, оскільки в ньому є занадто мало інформації.
— Даніель В.

2
@DanFromGermany Ви можете спробувати опублікувати власне запитання, можливо, це не зовсім та сама проблема.
— Ванні Тотаро

69

У мене була така ж проблема. Переконайтесь, що у вашому сценарії не було

#!/bin/sh 

вгорі вашого сценарію. Натомість слід додати

#!/bin/bash

5
Я використав, #!bin/bashі sh script.shвін все ще дав мені повідомлення про помилку. Потім ./script.shпрацює.
— whyisyoung

Якщо у вашому файлі відсутній шебанг у верхній частині, додавання #!/bin/bashтакож виправить неправильну заміну .
— Джеймі

1
@whyisyoung для вашої змінної може бути крапка (.) у її імені. Це дає поганий субст. помилка.
— користувач13107

4
@whyisyoung #!рядок використовується лише при безпосередньому виконанні сценарію. Якщо ви користуєтеся, sh script.shто лінія повністю ігнорується.
— bfontaine

35

Для інших, які приїжджають сюди, це точне повідомлення також з’явиться при використанні синтаксису змінної env для команд, наприклад ${which sh}замість правильної$(which sh)


21

У вашому синтаксисі сценаріїв є дійсним bash та good.

Можливі причини відмови:

  1. Ваша bashнасправді не bash, але kshчи якась інша оболонка, яка не розуміє підстановку параметрів bash. Тому що ваш сценарій виглядає чудово і працює з bash. Зробіть ls -l /bin/bashі перевірте, чи справді це баш та не пов'язаний з якоюсь іншою оболонкою.

  2. Якщо у вас є bash у вашій системі, то, можливо, ви виконуєте свій скрипт неправильно, як-от: ksh script.shабо sh script.sh(і ваша оболонка за замовчуванням не є bash). Оскільки у вас є належний шебанг, якщо ви б'єтесь ./script.shабо маєте bash ./script.shбути добре.


7
Я був би здивований, якби /bin/bash(ні /bin/sh) колись були пов'язані з іншою оболонкою.
— чепнер

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}'Перед Башем 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
Доказ про посилання @Qна додавання в bash-4.4.
— x-yuri

2

Обидва - bash або dash - працюють, але синтаксис повинен бути:

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

1
Це зовсім інша операція. Крім того, оскільки ОП дотримувалася належних практик, використовуючи імена змінних малих регістрів (див. 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

Я два рази додавав знак долара в виразі фігурними дужками в баші:

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.