bash: Pergantian Buruk

148
#!/bin/bash

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

Skrip bash ini memberi saya kesalahan substitusi buruk di Ubuntu. Bantuan apa pun akan sangat dihargai.

Arindam Choudhury
sumber
Ini bekerja dengan baik untuk saya. Apa yang ingin Anda capai?
fedorqui 'SO stop harming'
Saya mencoba untuk membagi jobname menjadi dua: job_201312161447 dan 0003. Ini memberikan kesalahan ini hanya ketika saya mencoba menjalankan ini di ubuntu.
Arindam Choudhury
Mmmm aneh. Bagaimana jika Anda menggunakan cut? cut -d_ -f1,2 <<< "$jobname"dan cut -d_ -f3 <<< "$jobname"membuatnya
fedorqui 'SO stop harming'
Terima kasih. tetapi mengapa jobname_pre = $ {jobname: 0: 16} memberi kesalahan
Arindam Choudhury
1
@ tukang lumpur Anda benar, saya melihat bahwa jika Anda melakukannya sh script.shmendapat kesalahan "substitusi buruk".
fedorqui 'SO stop harming'

Jawaban:

200

Shell default ( /bin/sh) di bawah Ubuntu menunjuk ke dash, bukan bash.

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

Jadi jika Anda chmod +x your_script_file.shdan kemudian menjalankannya ./your_script_file.sh, atau jika Anda menjalankannya bash your_script_file.sh, itu akan berfungsi dengan baik.

Menjalankannya dengan sh your_script_file.shtidak akan berfungsi karena garis hashbang akan diabaikan dan skrip akan ditafsirkan oleh dash, yang tidak mendukung sintaks substitusi string itu.

Vanni Totaro
sumber
2
Dia menggunakan /bin/bashsehingga jawaban Anda tidak cocok ?! Di mana Anda membaca dia menggunakan /bin/shatau sh script.sh?
Daniel W.
4
@DanFromGermany karena itulah satu-satunya alasan untuk kesalahan itu, yaitu dia menjalankan script dengan cara yang tidak mempertimbangkan hashbang, dan sintaks bash tidak didukung oleh beberapa shell lain (mungkin dash). Pertanyaan tidak selalu berisi semua detail yang diperlukan, dan kita harus bergabung dengan titik-titik ... tetap merasa ragu untuk menurunkan jawaban saya.
Vanni Totaro
2
Saya tidak perlu downvote. Saya memiliki pesan kesalahan yang sama bad substitutiondan saya hanya berusaha mengumpulkan informasi tetapi pertanyaan ini tidak membantu karena memiliki informasi yang terlalu sedikit.
Daniel W.
2
@DanFromGermany Anda dapat mencoba memposting pertanyaan Anda sendiri, mungkin itu bukan masalah yang sama persis.
Vanni Totaro
69

Saya memiliki masalah yang sama. Pastikan skrip Anda tidak punya

#!/bin/sh 

di bagian atas skrip Anda. Sebaliknya, Anda harus menambahkan

#!/bin/bash
Tamu
sumber
5
Saya menggunakan #!bin/bashdan sh script.sh, itu masih memberi saya pesan kesalahan. Lalu ./script.shbekerja.
whyisyoung
Jika file Anda kehilangan shebang di bagian atas menambahkan #!/bin/bashjuga akan memperbaiki substitusi buruk .
Jamie
1
@whyyoyoung, variabel Anda mungkin memiliki titik (.) dalam namanya. Ini memberikan subst yang buruk. kesalahan.
user13107
4
@whyyoyoung #!baris digunakan hanya ketika Anda menjalankan skrip Anda secara langsung. Jika Anda menggunakan sh script.shjalur ini sepenuhnya diabaikan.
bfontaine
35

Untuk orang lain yang tiba di sini, pesan persis ini juga akan muncul ketika menggunakan sintaks env variabel untuk perintah, misalnya ${which sh}bukan yang benar$(which sh)

Nacho Coloma
sumber
21

Sintaks skrip Anda valid dan bagus.

Kemungkinan penyebab kegagalan:

  1. Anda bashbukan benar-benar bash tetapi kshatau beberapa shell lain yang tidak mengerti substitusi parameter bash. Karena skrip Anda terlihat bagus dan berfungsi dengan bash. Lakukan ls -l /bin/bashdan periksa itu benar-benar bash dan tidak terhubung ke beberapa shell lain.

  2. Jika Anda memiliki bash di sistem Anda, maka Anda mungkin mengeksekusi skrip Anda dengan cara yang salah seperti: ksh script.shatau sh script.sh(dan shell default Anda bukan bash). Karena Anda memiliki shebang yang tepat, jika Anda memiliki bash ./script.shatau bash ./script.shharus baik-baik saja.

PP
sumber
7
Saya akan terkejut jika /bin/bash(tidak /bin/sh) pernah dikaitkan dengan shell yang berbeda.
chepner
ksh sebenarnya dari mana sebagian besar ekstensi sintaksis bash berasal; itu pasti memiliki sintaks ekspansi parameter spesifik yang dimaksud. Saya tidak akan cenderung menyarankan menyebutnya sebagai shell tidak mungkin mampu.
Charles Duffy
7

Coba jalankan skrip secara eksplisit menggunakan perintah bash daripada hanya menjalankannya sebagai executable.

Titik biru muda
sumber
3
Bagus Akan sangat membantu untuk menambahkan beberapa sampel output untuk membuatnya lebih jelas, dengan menggunakan sh scriptdan bash script... saran saya :)
fedorqui 'SO stop harming'
4

Juga, pastikan Anda tidak memiliki string kosong untuk baris pertama skrip Anda.

yaitu pastikan #!/bin/bashadalah baris paling pertama dari skrip Anda.

Wizurd
sumber
3

Tidak relevan dengan contoh Anda, tetapi Anda juga bisa mendapatkan Bad substitutionkesalahan di Bash untuk sintaksis substitusi apa pun yang tidak dikenali Bash. Ini bisa jadi:

  • Ruang putih menyimpang. Misalnyabash -c '${x }'
  • Salah ketik. Misalnyabash -c '${x;-}'
  • Fitur yang ditambahkan di versi Bash yang lebih baru. Misal bash -c '${x@Q}'sebelum Bash 4.4.

Jika Anda memiliki beberapa pergantian dalam ekspresi yang sama, Bash mungkin tidak terlalu membantu dalam menentukan dengan tepat ekspresi bermasalah. Misalnya:

$ bash -c '"${x } multiline string
$y"'
bash: line 1: ${x } multiline string
$y: bad substitution
Daniel Darabos
sumber
2
Ini adalah pukulan pertama untuk Bad substitutionjadi saya pikir saya akan memasukkan kasus yang kami temui. (Itu @Qdi Bash 4.3 bersembunyi dalam ekspresi multi-line yang panjang.)
Daniel Darabos
2
Ini adalah masalah saya ketika menjalankan Bash 3.x di mac
coloradocolby
2
Prooflink tentang @Qpenambahan bash-4.4.
x-yuri
2

Keduanya - bash atau dash - berfungsi, tetapi sintaksnya harus:

FILENAME=/my/complex/path/name.ext
NEWNAME=${FILENAME%ext}new
Hagen
sumber
1
Itu operasi yang sama sekali berbeda. Juga, karena OP mengikuti praktik baik dengan menggunakan nama variabel huruf kecil (lihat pubs.opengroup.org/onlinepubs/9699919799/basedefs/… - nama huruf besar digunakan untuk variabel yang bermakna pada OS atau shell; nama huruf kecil adalah dicadangkan untuk penggunaan aplikasi), itu harus dilakukan juga.
Charles Duffy
0

Sepertinya "+ x" menyebabkan masalah:

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
sumber
0

Saya menambahkan tanda dolar dua kali dalam ekspresi dengan kurung kurawal di bash:

cp -r $PROJECT_NAME ${$PROJECT_NAME}2

dari pada

cp -r $PROJECT_NAME ${PROJECT_NAME}2
sashoalm
sumber
-1

Saya telah menemukan bahwa masalah ini disebabkan oleh jawaban yang ditandai atau Anda memiliki garis atau ruang sebelum deklarasi bash

Ahmed Oladele
sumber