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.