bash: Kötü Değiştirme


159
#!/bin/bash

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

Bu bash betiği bana Ubuntu'da Kötü ikame hatası veriyor . Herhangi bir yardım çok takdir edilecektir.


Benim için iyi çalışıyor. Neyi başarmaya çalışıyorsun?
fedorqui

İş adını ikiye bölmeye çalışıyorum: job_201312161447 ve 0003. Bu hatayı sadece ubuntu'da çalıştırmaya çalıştığımda veriyor.
Arindam Choudhury

Mmmm tuhaf. Ya kullanırsan cut? cut -d_ -f1,2 <<< "$jobname"and cut -d_ -f3 <<< "$jobname"make it
fedorqui '

1
Teşekkürler. ama jobname_pre = $ {jobname: 0: 16} neden hata verdi
Arindam Choudhury

2
@bludger haklısın, görüyorum ki eğer yaparsan sh script.sh"Kötü ikame" hatası alıyor.
fedorqui

Yanıtlar:


209

/bin/shUbuntu altındaki varsayılan kabuk ( ) dash, değil bash.

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

Yani siz chmod +x your_script_file.shve sonra onu çalıştırırsanız ./your_script_file.shveya birlikte çalıştırırsanız bash your_script_file.sh, iyi çalışması gerekir.

sh your_script_file.shOnunla çalıştırmak işe yaramayacak çünkü hashbang satırı yok sayılacak ve betik tarafından yorumlanacak dash, bu dize değiştirme sözdizimini desteklemiyor.


2
/bin/bashCevabınız uymuyor diye kullanıyor mu ?! Nerede o kullanıyor okuyorsun /bin/shya sh script.sh?
Daniel W.

4
@DanFromGermany çünkü bu hatanın tek nedeni bu, yani komut dosyasını hashbang'ı dikkate almayan bir şekilde çalıştırıyor ve bu bash sözdizimi başka bir kabuk (muhtemelen çizgi) tarafından desteklenmiyor. Sorular her zaman gerekli tüm ayrıntıları içermez ve noktaları birleştirmeliyiz ... yine de cevabımı olumsuz yönde oylayabilirsiniz.
Vanni Totaro

2
Olumsuz oy kullanmama gerek yok. Aynı hata mesajını alıyorum bad substitutionve sadece bilgi toplamaya çalışıyorum ama bu soru yardımcı olmuyor çünkü çok az bilgi içeriyor.
Daniel W.

2
@DanFromGermany kendi sorunuzu göndermeyi deneyebilirsiniz, belki de tam olarak aynı sorun değildir.
Vanni Totaro

75

Ben de aynı sorunu yaşadım. Komut dosyanızın sahip olmadığından emin olun.

#!/bin/sh 

senaryonuzun en üstünde. Bunun yerine eklemelisiniz

#!/bin/bash

8
Kullandım #!bin/bashve sh script.shhala bana hata mesajını verdi. Sonra ./script.shçalışır.
whyisyoung

Dosyanızda üstte bir işaret eksikse, ekleme Kötü ikameyi#!/bin/bash de düzeltecektir .
Jamie

1
@whyisyoung değişkeninizin adında bir nokta (.) olabilir. Kötü altlık verir. hata.
user13107

4
@whyisyoung #!satır yalnızca betiğinizi doğrudan çalıştırdığınızda kullanılır. sh script.shHat kullanırsanız tamamen göz ardı edilir.
bfontaine

37

Buraya gelenler için, bu tam mesaj, komutlar için env değişken sözdizimi kullanıldığında da görünecektir, örneğin ${which sh}doğru yerine$(which sh)


21

Komut dosyası söz diziminiz geçerli bir bash ve iyi.

Başarısızlığın olası nedenleri:

  1. Sizin bashgerçekten bash değil, kshya da bash'ın parametre değiştirmesini anlamayan başka bir kabuk. Çünkü betiğiniz iyi görünüyor ve bash ile çalışıyor. Yapın ls -l /bin/bashve kontrol edin, gerçekten bash ve başka bir kabuğa sym-bağlı değil.

  2. Sisteminizde bash varsa, komut dosyanızı yanlış şekilde çalıştırıyor olabilirsiniz: ksh script.shveya sh script.sh(ve varsayılan kabuğunuz bash değildir). Düzgün bir shebang yaptığınız için, eğer bashınız varsa ./script.shveya bash ./script.shiyi olmalıysanız .


8
Farklı bir kabuğa bağlanmış olsaydım /bin/bash(olmasaydı /bin/sh) şaşırırdım.
chepner

ksh aslında bash'ın sözdizimi uzantılarının çoğunun kaynaklandığı yerdir; o kesinlikle söz konusu parametre genişletme sözdizimi vardır. Yetenekli olma olasılığı düşük bir kabuk olarak adlandırmayı önerme eğiliminde değilim.
Charles Duffy


5

Örneğinizle ilgili değildir, ancak Bad substitutionBash'in tanımadığı herhangi bir ikame sözdizimi için Bash'de hata alabilirsiniz . Bu olabilir:

  • Başıboş beyaz boşluk. Örneğinbash -c '${x }'
  • Bir yazım hatası. Örneğinbash -c '${x;-}'
  • Daha sonraki bir Bash sürümünde eklenen bir özellik. Örneğin bash -c '${x@Q}'Bash 4.4 önce.

Aynı ifadede birden fazla ikameniz varsa, Bash sorunlu ifadeyi tam olarak belirlemede çok yardımcı olmayabilir. Örneğin:

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

2
Bu ilk isabet, Bad substitutionbu yüzden karşılaştığımız davayı da dahil edeceğimi düşündüm. ( @QBash 4.3'te uzun çok satırlı bir ifadede saklanıyordu.)
Daniel Darabos

2
Mac'te Bash 3.x'i çalıştırırken sorunum buydu
coloradocolby

2
Prooflink ile ilgili @Qolarak ilave edilir bash-4.4.
x-yuri

4

Ayrıca, komut dosyanızın ilk satırı için boş bir dizeye sahip olmadığınızdan emin olun.

yani #!/bin/bashbetiğinizin ilk satırının olduğundan emin olun .


2

Her ikisi de - bash veya tire - çalışır, ancak sözdiziminin şöyle olması gerekir:

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

1
Bu tamamen farklı bir operasyon. Ayrıca, OP, küçük harfli değişken adları kullanarak iyi uygulamaları takip ettiğinden (bkz. Pubs.opengroup.org/onlinepubs/9699919799/basedefs/… - işletim sistemi veya kabuk anlamında değişkenler için büyük harfli adlar kullanılır; uygulama kullanımı için ayrılmıştır), aynı şekilde yapmak zorundadır.
Charles Duffy

1

Bash'de küme parantezli bir ifadeye iki kez dolar işareti ekliyordum:

cp -r $PROJECT_NAME ${$PROJECT_NAME}2

onun yerine

cp -r $PROJECT_NAME ${PROJECT_NAME}2

0

Görünüşe göre "+ x" sorunlara neden oluyor:

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

Ahmed ve RavinderSingh13'e katılıyorum Benzer bir sorunla karşılaştım ve bazı komut dosyalarımın ilk satırında "#! / Bin / bash" dan hemen önce bir beyaz boşluk olduğunu gördüm. Bu boşluğun nasıl göründüğünü hiç anlamadım ama tüm senaryomun herhangi bir satırın başında en az bir boşluk var


Bunun nedeni, shebang'ın (bir açıklama (#) ile başlayan ilk komut dosyası satırı ve ardından ünlem işareti (!) Ve bir yürütülebilir dosyanın bu boşlukla bölünmesidir. Satır bir yorumla BAŞLAMAZ, bu nedenle komut dosyası bash yerine sh tarafından yürütülür , ve alt dizeyi ayrıştıramaz
netizen

-1

Bu sorunun ya işaretli cevaptan kaynaklandığını ya da bash bildiriminden önce bir satır ya da boşluk olduğunu buldum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.