Bash: Schlechte Substitution

148
#!/bin/bash

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

Dieses Bash-Skript gibt mir einen fehlerhaften Substitutionsfehler unter Ubuntu. Jede Hilfe wird sehr geschätzt.

Arindam Choudhury
quelle
Es funktioniert gut für mich. Was versuchst du zu erreichen?
Fedorqui 'SO hör auf zu schaden'
Ich versuche, den Jobnamen in zwei Teile zu teilen: job_201312161447 und 0003. Dieser Fehler wird nur ausgegeben, wenn ich versuche, ihn auf Ubuntu auszuführen.
Arindam Choudhury
Mmmm seltsam. Was ist, wenn Sie verwenden cut? cut -d_ -f1,2 <<< "$jobname"und cut -d_ -f3 <<< "$jobname"mach es
fedorqui 'SO hör auf'
Vielen Dank. aber warum jobname_pre = $ {jobname: 0: 16} gab Fehler
Arindam Choudhury
1
@bludger du hast recht, ich sehe, dass wenn du es tust, sh script.shes einen "Bad Substitution" Fehler gibt.
Fedorqui 'SO hör auf zu schaden'

Antworten:

200

Die Standard-Shell ( /bin/sh) unter Ubuntu zeigt auf dash, nicht bash.

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

Wenn Sie es chmod +x your_script_file.shdann ausführen ./your_script_file.shoder dann ausführen bash your_script_file.sh, sollte es einwandfrei funktionieren.

Das Ausführen mit sh your_script_file.shfunktioniert nicht, da die Hashbang-Zeile ignoriert und das Skript von interpretiert wird dash, was diese Syntax für das Ersetzen von Zeichenfolgen nicht unterstützt.

Vanni Totaro
quelle
2
Er benutzt, /bin/bashdamit deine Antwort nicht passt?! Wo liest du, was er benutzt /bin/shoder sh script.sh?
Daniel W.
4
@DanFromGermany, weil dies der einzige Grund für diesen Fehler ist, dh er führt das Skript auf eine Weise aus, die den Hashbang nicht berücksichtigt, und diese Bash-Syntax wird von keiner anderen Shell (wahrscheinlich Bindestrich) unterstützt. Fragen enthalten nicht immer alle erforderlichen Details, und wir müssen uns den Punkten anschließen. Sie können meine Antwort trotzdem ablehnen.
Vanni Totaro
2
Ich muss nicht abstimmen. Ich habe die gleiche Fehlermeldung bad substitutionund versuche nur, Informationen zu sammeln, aber diese Frage hilft nicht, weil sie zu wenige Informationen enthält.
Daniel W.
2
@DanFromGermany Sie könnten versuchen, Ihre eigene Frage zu stellen, vielleicht ist es nicht genau das gleiche Problem.
Vanni Totaro
69

Ich hatte das gleiche Problem. Stellen Sie sicher, dass Ihr Skript nicht hatte

#!/bin/sh 

oben in Ihrem Skript. Stattdessen sollten Sie hinzufügen

#!/bin/bash
Gast
quelle
5
Ich benutzte #!bin/bashund sh script.shes gab mir immer noch die Fehlermeldung. Dann ./script.shfunktioniert.
Whyisyoung
Wenn in Ihrer Datei ein Shebang oben fehlt, wird durch das Hinzufügen #!/bin/bashauch die fehlerhafte Ersetzung behoben .
Jamie
1
@whyisyoung Ihre Variable könnte einen Punkt (.) im Namen haben. Es gibt schlechte subst. Error.
user13107
4
@whyisyoung Die #!Zeile wird nur verwendet, wenn Sie Ihr Skript direkt ausführen. Wenn Sie sh script.shdie Zeile verwenden, wird sie vollständig ignoriert.
Bfontaine
35

Für andere, die hier ankommen, wird diese genaue Meldung auch angezeigt, wenn die Syntax der env-Variablen für Befehle verwendet wird, z. B. ${which sh}anstelle der richtigen$(which sh)

Nacho Coloma
quelle
21

Ihre Skriptsyntax ist gültig und gut.

Mögliche Fehlerursachen:

  1. Sie bashsind nicht wirklich bash, sondern ksheine andere Shell, die die Parametersubstitution von bash nicht versteht. Weil dein Skript gut aussieht und mit Bash funktioniert. Tun Sie ls -l /bin/bashund überprüfen Sie, ob es wirklich Bash ist und nicht mit einer anderen Shell verknüpft ist.

  2. Wenn Sie Bash auf Ihrem System haben, führen Sie Ihr Skript möglicherweise falsch aus: ksh script.shoder sh script.sh(und Ihre Standard-Shell ist nicht Bash). Da Sie richtigen Shebang haben, wenn Sie Bash haben ./script.shoder bash ./script.shin Ordnung sein sollten.

PP
quelle
7
Es würde mich wundern, wenn /bin/bash(nicht /bin/sh) jemals eine andere Shell verwendet würde.
Chepner
ksh ist eigentlich der Ursprung der meisten Syntaxerweiterungen von bash. es hat sicherlich die spezifische Parametererweiterungssyntax in Frage. Ich würde nicht vorschlagen, es als eine Shell zu bezeichnen, die wahrscheinlich nicht fähig ist.
Charles Duffy
7

Versuchen Sie, das Skript explizit mit dem Befehl bash auszuführen, anstatt es nur als ausführbare Datei auszuführen.

Blass-blauer Punkt
quelle
3
Gut. Es wäre hilfreich , eine Beispielausgabe hinzufügen , um es deutlicher zu machen, durch die Verwendung sh scriptund bash script... mein Vorschlag :)
fedorqui ‚SO aufhören zu schaden‘
4

Stellen Sie außerdem sicher, dass Sie keine leere Zeichenfolge für die erste Zeile Ihres Skripts haben.

Stellen Sie also sicher, dass dies #!/bin/bashdie allererste Zeile Ihres Skripts ist.

wizurd
quelle
3

Nicht relevant für Ihr Beispiel, aber Sie können auch den Bad substitutionFehler in Bash für jede Substitutionssyntax erhalten, die Bash nicht erkennt. Das könnte sein:

  • Streunende Leerzeichen. Z.Bbash -c '${x }'
  • Ein Tippfehler. Z.Bbash -c '${x;-}'
  • Eine Funktion, die in einer späteren Bash-Version hinzugefügt wurde. ZB bash -c '${x@Q}'vor Bash 4.4.

Wenn Sie mehrere Substitutionen im selben Ausdruck haben, ist Bash möglicherweise nicht sehr hilfreich, um den problematischen Ausdruck zu lokalisieren. Z.B:

$ bash -c '"${x } multiline string
$y"'
bash: line 1: ${x } multiline string
$y: bad substitution
Daniel Darabos
quelle
2
Dies ist der erste Treffer für, Bad substitutionalso dachte ich, ich würde den Fall einschließen, auf den wir gestoßen sind. (Es war @Qin Bash 4.3 und versteckte sich in einem langen mehrzeiligen Ausdruck.)
Daniel Darabos
2
Dies war mein Problem beim Ausführen von Bash 3.x auf Mac
Coloradocol bis
2
Prooflink bezüglich @Qdes Hinzufügens in bash-4.4.
x-yuri
2

Beide - Bash oder Dash - funktionieren, aber die Syntax muss lauten:

FILENAME=/my/complex/path/name.ext
NEWNAME=${FILENAME%ext}new
Hagen
quelle
1
Das ist eine ganz andere Operation. Da das OP bewährte Verfahren unter Verwendung von Variablennamen in Kleinbuchstaben befolgte (siehe pubs.opengroup.org/onlinepubs/9699919799/basedefs/… ), werden Großbuchstaben für Variablen verwendet, die für das Betriebssystem oder die Shell von Bedeutung sind vorbehalten für Anwendungszwecke), es ist ebenfalls erforderlich, dies zu tun.
Charles Duffy
0

Sieht aus wie "+ x" Probleme verursacht:

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
Andrew Knutsen
quelle
0

Ich habe zweimal ein Dollarzeichen in einen Ausdruck mit geschweiften Klammern in Bash eingefügt:

cp -r $PROJECT_NAME ${$PROJECT_NAME}2

anstatt

cp -r $PROJECT_NAME ${PROJECT_NAME}2
Sashoalm
quelle
-1

Ich habe festgestellt, dass dieses Problem entweder durch die markierte Antwort verursacht wird oder dass Sie vor der Bash-Deklaration eine Zeile oder ein Leerzeichen haben

Ahmed Oladele
quelle