bash: Zła zamiana


148
#!/bin/bash

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

Ten skrypt bash daje mi zły błąd zastępowania w systemie Ubuntu. Jakakolwiek pomoc będzie doceniona.


Dla mnie to działa dobrze. Co próbujesz osiągnąć?
fedorqui „SO przestań szkodzić”

Próbuję podzielić nazwę zadania na dwie: job_201312161447 i 0003. Podaje ten błąd tylko wtedy, gdy próbuję go uruchomić na ubuntu.
Arindam Choudhury

Mmmm dziwne. A jeśli użyjesz cut? cut -d_ -f1,2 <<< "$jobname"i cut -d_ -f3 <<< "$jobname"zrób to
fedorqui SO przestań szkodzić

dzięki. ale dlaczego jobname_pre = $ {jobname: 0: 16} dało błąd
Arindam Choudhury,

1
@bludger masz rację, widzę, że jeśli to zrobisz sh script.sh, pojawia się błąd „Zła zamiana”.
fedorqui „SO przestań szkodzić”

Odpowiedzi:


200

Domyślna powłoka ( /bin/sh) w Ubuntu wskazuje na dashnie bash.

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

Więc jeśli chmod +x your_script_file.shuruchomisz go z ./your_script_file.shlub jeśli uruchomisz go z bash your_script_file.sh, powinno działać dobrze.

Uruchomienie go z sh your_script_file.shnie zadziała, ponieważ linia hashbang zostanie zignorowana, a skrypt zostanie zinterpretowany przez dash, który nie obsługuje składni zastępowania ciągów.


2
Używa, /bin/bashwięc twoja odpowiedź nie pasuje ?! Gdzie czytasz, że on używa /bin/shlub sh script.sh?
Daniel W.

4
@DanFromGermany, ponieważ jest to jedyny powód tego błędu, tj. Uruchamia skrypt w sposób, który nie uwzględnia hashbang, a składnia basha nie jest obsługiwana przez jakąś inną powłokę (prawdopodobnie myślnik). Pytania nie zawsze zawierają wszystkie potrzebne szczegóły i musimy połączyć kropki ... w każdym razie nie krępuj się, aby przegłosować moją odpowiedź.
Vanni Totaro

2
Nie muszę głosować przeciw. Mam ten sam komunikat o błędzie bad substitutioni po prostu próbuję zebrać informacje, ale to pytanie nie pomaga, ponieważ zawiera zbyt mało informacji.
Daniel W.

2
@DanFromGermany możesz spróbować zadać własne pytanie, może to nie jest dokładnie ten sam problem.
Vanni Totaro

69

Miałem ten sam problem. Upewnij się, że Twój skrypt nie ma

#!/bin/sh 

u góry skryptu. Zamiast tego powinieneś dodać

#!/bin/bash

5
Użyłem #!bin/bashi sh script.shnadal wyświetlał mi komunikat o błędzie. Wtedy ./script.shdziała.
whyisyoung

Jeśli w Twoim pliku brakuje znaku shebang na górze, dodanie #!/bin/bashrównież naprawi złe podstawienie .
Jamie

1
@whyisyoung Twoja zmienna może mieć w nazwie kropkę (.). Daje zły substytut. błąd.
user13107,

4
@whyisyoung #!linia jest używana tylko wtedy, gdy wykonujesz skrypt bezpośrednio. Jeśli używasz sh script.shlinii jest całkowicie ignorowana.
bfontaine

35

Dla innych, którzy tu przybędą, ta dokładna wiadomość pojawi się również podczas używania składni zmiennej env dla poleceń, na przykład ${which sh}zamiast prawidłowego$(which sh)


21

Składnia twojego skryptu jest poprawna bash i dobra.

Możliwe przyczyny niepowodzenia:

  1. Twoja bashnie jest tak naprawdę bash ale kshczy jakaś inna powłoka, która nie rozumie parametr podstawienie atakujących za. Ponieważ twój skrypt wygląda dobrze i działa z bash. Zrobić ls -l /bin/bashi sprawdzić to naprawdę bash i nie sym-przyłączone do innego zbiornika.

  2. Jeśli masz bash w swoim systemie, być może wykonujesz swój skrypt w niewłaściwy sposób, na przykład: ksh script.shlub sh script.sh(a Twoją domyślną powłoką nie jest bash). Ponieważ masz porządny shebang, jeśli masz bash ./script.shlub bash ./script.shpowinno być dobrze.


7
Zdziwiłbym się, gdyby /bin/bash(nie /bin/sh) były kiedykolwiek połączone z inną powłoką.
chepner

ksh jest właściwie miejscem, z którego pochodzi większość rozszerzeń składni basha; z pewnością ma określoną składnię rozszerzania parametrów. Nie miałbym skłonności sugerować nazywania go skorupą, która prawdopodobnie nie będzie w stanie.
Charles Duffy


4

Upewnij się również, że w pierwszym wierszu skryptu nie ma pustego ciągu.

tzn. upewnij się, że #!/bin/bashjest to pierwsza linia skryptu.


3

Nie dotyczy twojego przykładu, ale możesz również otrzymać Bad substitutionbłąd w Bash dla dowolnej składni podstawiania, której Bash nie rozpoznaje. To mógłby być:

  • Bezpańskie białe znaki. Na przykładbash -c '${x }'
  • Literówka. Na przykładbash -c '${x;-}'
  • Funkcja, która została dodana w późniejszej wersji Bash. Np. bash -c '${x@Q}'Przed Bash 4.4.

Jeśli masz wiele podstawień w tym samym wyrażeniu, Bash może nie być zbyt pomocny w zlokalizowaniu problematycznego wyrażenia. Na przykład:

$ bash -c '"${x } multiline string
$y"'
bash: line 1: ${x } multiline string
$y: bad substitution

2
To pierwsze trafienie, Bad substitutionwięc pomyślałem, że uwzględnię przypadek, na który się natknęliśmy. (To było @Qw Bash 4.3 ukrywając się w długim, wieloliniowym wyrażeniu.)
Daniel Darabos

2
To był mój problem podczas uruchamiania Bash 3.x na komputerze Mac
coloradocolby

2
Link potwierdzający dotyczący @Qdodania bash-4.4.
x-yuri

2

Oba - bash lub dash - działają, ale składnia musi być następująca:

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

1
To zupełnie inna operacja. Ponadto, ponieważ program operacyjny postępował zgodnie z dobrymi praktykami, używając nazw zmiennych składających się z małych liter (patrz pubs.opengroup.org/onlinepubs/9699919799/basedefs/ ... - nazwy wielkimi literami są używane dla zmiennych mających znaczenie dla systemu operacyjnego lub powłoki; małe litery są zarezerwowane do użytku aplikacji), należy postępować podobnie.
Charles Duffy

0

Wygląda na to, że „+ x” powoduje problemy:

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

Dwa razy dodawałem znak dolara w wyrażeniu z nawiasami klamrowymi w bash:

cp -r $PROJECT_NAME ${$PROJECT_NAME}2

zamiast

cp -r $PROJECT_NAME ${PROJECT_NAME}2

-1

Odkryłem, że ten problem jest spowodowany zaznaczoną odpowiedzią lub masz linię lub spację przed deklaracją bash

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.