bash: sostituzione errata


148
#!/bin/bash

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

Questo script bash mi dà un errore di sostituzione Bad su Ubuntu. Qualsiasi aiuto sarà molto apprezzato.


Sta funzionando bene per me. Cosa stai cercando di realizzare?
fedorqui "SO smettere di danneggiare" il

Sto cercando di dividere il nome del lavoro in due: job_201312161447 e 0003. Sta dando questo errore solo quando sto cercando di eseguirlo su Ubuntu.
Arindam Choudhury,

Mmmm strano. E se lo usi cut? cut -d_ -f1,2 <<< "$jobname"e cut -d_ -f3 <<< "$jobname"farlo
fedorqui "COSÌ smetti di danneggiare" il

Grazie. ma perché jobname_pre = $ {jobname: 0: 16} ha dato errore
Arindam Choudhury

1
@bludger hai ragione, vedo che se lo fai sh script.shsi ottiene un errore "Sostituzione errata".
fedorqui "SO smettere di danneggiare" il

Risposte:


200

La shell di default ( /bin/sh) sotto Ubuntu punta dash, no bash.

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

Quindi, se lo chmod +x your_script_file.shesegui, quindi ./your_script_file.sh, o se lo esegui bash your_script_file.sh, dovrebbe funzionare correttamente .

L'esecuzione con sh your_script_file.shnon funzionerà perché la riga hashbang verrà ignorata e lo script verrà interpretato da dash, il che non supporta la sintassi di sostituzione di stringa.


2
Sta usando /bin/bashquindi la tua risposta non si adatta ?! Dove leggi che sta usando /bin/sho sh script.sh?
Daniel W.

4
@DanFromGermany perché questa è l'unica ragione per quell'errore, cioè sta eseguendo lo script in un modo che non considera l'hashbang e che la sintassi bash non è supportata da qualche altra shell (probabilmente trattino). Le domande non contengono sempre tutti i dettagli necessari e dobbiamo unire i punti ... comunque sentiti libero di votare la mia risposta.
Vanni Totaro,

2
Non ho bisogno di sottovalutare. Ho lo stesso messaggio di errore bad substitutione sto solo cercando di raccogliere informazioni, ma questa domanda non aiuta perché contiene troppe informazioni.
Daniel W.

2
@DanFromGermany potresti provare a pubblicare la tua domanda, forse non è esattamente lo stesso problema.
Vanni Totaro,

69

Ho avuto lo stesso problema. Assicurati che il tuo script non lo abbia fatto

#!/bin/sh 

nella parte superiore della tua sceneggiatura. Invece, dovresti aggiungere

#!/bin/bash

5
Ho usato #!bin/bashe sh script.sh, mi ha ancora dato il messaggio di errore. Quindi ./script.shfunziona.
whyisyoung

Se nel tuo file manca uno shebang in alto, l'aggiunta #!/bin/bashrisolverà anche la sostituzione Bad .
Jamie,

1
@whyisyoung la tua variabile potrebbe avere un punto (.) nel suo nome. Dà una cattiva sostituzione. errore.
user13107

4
@whyisyoung la #!riga viene utilizzata solo quando si esegue direttamente lo script. Se si utilizza sh script.shla linea viene completamente ignorata.
bfontaine,

35

Per gli altri che arrivano qui, questo messaggio esatto apparirà anche quando si utilizza la sintassi della variabile env per i comandi, ad esempio ${which sh}invece del corretto$(which sh)


21

La sintassi dello script è valida bash e buona.

Possibili cause dell'errore:

  1. Il tuo bashnon è veramente bash ma ksho qualche altra shell che non comprende la sostituzione dei parametri di bash. Perché la tua sceneggiatura sembra a posto e funziona con bash. Fai ls -l /bin/bashe controlla che sia davvero bash e non collegato a qualche altra shell.

  2. Se hai bash sul tuo sistema, allora potresti eseguire il tuo script nel modo sbagliato come: ksh script.sho sh script.sh(e la tua shell predefinita non è bash). Dal momento che hai un vero shebang, se hai bash ./script.sho bash ./script.shdovrebbe andare bene.


7
Sarei sorpreso se /bin/bash(non /bin/sh) fosse mai stato collegato a una shell diversa.
Chepner,

ksh è in realtà da dove proviene la maggior parte delle estensioni di sintassi di bash; ha certamente la sintassi specifica di espansione dei parametri in questione. Non tenderei a suggerire di chiamarlo come una shell che difficilmente sarà capace.
Charles Duffy,


4

Inoltre, assicurati di non avere una stringa vuota per la prima riga dello script.

cioè assicurati che #!/bin/bashsia la prima riga del tuo script.


3

Non pertinente al tuo esempio, ma puoi anche ottenere l' Bad substitutionerrore in Bash per qualsiasi sintassi di sostituzione che Bash non riconosce. Questo potrebbe essere:

  • Spazi vuoti. Per esempiobash -c '${x }'
  • Un errore di battitura Per esempiobash -c '${x;-}'
  • Una funzione che è stata aggiunta in una versione successiva di Bash. Ad esempio bash -c '${x@Q}'prima di Bash 4.4.

Se hai più sostituzioni nella stessa espressione, Bash potrebbe non essere molto utile per individuare l'espressione problematica. Per esempio:

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

2
Questo è il primo successo per Bad substitutioncui ho pensato di includere il caso in cui ci siamo imbattuti. (Era @Qin Bash 4.3 nascosto in una lunga espressione multilinea.)
Daniel Darabos,

2
Questo era il mio problema quando eseguivo Bash 3.x su mac
coloradocolby

2
Link di prova relativo all'aggiunta@Q in bash-4.4.
x-yuri,

2

Entrambi - bash o dash - funzionano, ma la sintassi deve essere:

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

1
È un'operazione completamente diversa. Inoltre, poiché l'OP stava seguendo le buone pratiche utilizzando i nomi delle variabili minuscole (vedi pubs.opengroup.org/onlinepubs/9699919799/basedefs/… - i nomi in maiuscolo vengono utilizzati per le variabili con significato per il sistema operativo o la shell; i nomi in minuscolo sono riservato all'uso dell'applicazione), è necessario fare altrettanto.
Charles Duffy,

0

Sembra che "+ x" causi problemi:

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

Stavo aggiungendo due volte un segno di dollaro in un'espressione con parentesi graffe in bash:

cp -r $PROJECT_NAME ${$PROJECT_NAME}2

invece di

cp -r $PROJECT_NAME ${PROJECT_NAME}2

-1

Ho scoperto che questo problema è causato dalla risposta contrassegnata o hai una riga o uno spazio prima della dichiarazione bash

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.