2008-09-19 20 views

cevap

96

yeterli değildir. Siz de değişken referans alıntı gerekir: Bu komut satırında printf ziyade echo kullanma alışkanlığı girmesini değebilir

me$ FOO="BAR * BAR" 
me$ echo "$FOO" 
BAR * BAR 
+0

Bu gizemli, neden bu? ne oluyor? – tofutim

3
FOO='BAR * BAR' 
echo "$FOO" 
+0

Bu çalışır, ancak tırnak ikiye katlama ilk satırda tek tırnak değiştirmek için gerekli değil:

#!/bin/bash GLOBIGNORE="*" curl_opts="-s --noproxy * -O" curl $curl_opts "$1" ## no filename expansion 

orijinal örneğe uygulanıyor. – finnw

+1

Hayır, öyle değil, ancak özel kabuk karakterleri içerecek ve herhangi bir değişiklik istemediğinizde tek tırnak kullanma alışkanlığı tercih edilir. – tzot

3
echo "$FOO" 
3

.

Bu örnekte, çok fayda sağlamaz, ancak daha karmaşık çıktılarda daha kullanışlı olabilir.

FOO="BAR * BAR" 
printf %s "$FOO" 
+0

Neden cehennemde? printf ayrı bir işlemdir (en azından bash'ta yerleşik değil) ve eko üzerinde hiçbir faydası olmadığını gösterdiğiniz printf'in kullanımı. – ddaa

+1

printf * bir * yerleşik * bash ve ben cevabımda söyledim "Bu örnekte çok fayda sağlamaz ama daha karmaşık çıktılarla daha kullanışlı olabilir. –

73

KISA CEVAP

diğerleri söylediler gibi - her zaman garip davranışları önlemek için değişkenleri alıntı olmalıdır. Bu yüzden echo $ foo yerine echo "$ foo" kullanın.

UZUN YANIT

Daha bunun yüzünde göründüğünden daha oluyor, çünkü bu örnek daha fazla açıklama garanti düşünüyorum.

  1. Parametre genişletme
  2. Dosya adı genişleme

: En karışıklık Eğer kabuk açıkçası yaptığını muhtemelen kendinize düşünce ilk örneğini koştu çünkü sonra devreye giriyor

Görebildiğim Yani ilk örneğinizden:

me$ FOO="BAR * BAR" 
me$ echo $FOO 

A fter parametre genişleme eşdeğerdir:

me$ echo BAR * BAR 

Ve Dosyaismi sonra eşdeğerdir:

me$ echo BAR file1 file2 file3 file4 BAR 

Ve sadece komut satırına echo BAR * BAR yazarsanız onlar eşdeğer olduğunu göreceksiniz.Parametre genişleme sonra

me$ FOO="BAR \* BAR" 
me$ echo $FOO 

denk olmalıdır:

Yani muhtemelen ikinci örnekten Yani

"Ben * kaçmak, ben dosya adı genişlemesini önleyebilir" Kendine düşünülen

me$ echo BAR \* BAR 

Ve dosyaismi sonra olmalıdır eşdeğer:

me$ echo BAR \* BAR 

Ve "echo BAR \ * BAR" komutunu doğrudan komut satırına yazmayı denerseniz, "BAR * BAR" yazdıracağından, dosya adı genişletme engellenerek önlenir.

Peki neden $ foo kullanmıyorsunuz?

Çünkü üçüncü bir genişleme gerçekleşir - Alıntı Kaldırma. bash manuel tırnak kaldırma itibaren geçerli: önceki açılımları sonra

, yukarıdaki açılımları birinden yol açmamıştır karakterler '\', ''' ve '' "her tırnaksız olaylar vardır kaldırıldı.

Yani komut satırına doğrudan komutu yazdığınızda edilir ne olur, kaçış karakteri BASH yankı komuta göndermeden önce kaldırır, böylece bir önceki genişleme sonucu değildir, ama içinde İkinci örnekte, "\ *" bir önceki Parametre genişletmesinin sonucuydu, bu yüzden DEĞİLDİR Sonuç olarak, echo "\ *" alır ve bu da yazdırır.

İlk örnek arasındaki fark dikkat edin - "*", Kaldırma Kaldırma tarafından kaldırılacak olan karakterlere dahil değildir.

Umarım bu mantıklıdır. Sonunda sonuç aynı - sadece alıntılar kullanın. Sadece Parameter ve Filename genişletmenin oynadığı durumlarda mantıken işe yarayan kaçış nedenini açıklayacağımı düşündüm. Bu eski konuya biraz eklemek gerekir

http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions

+0

Harika cevap! Şimdi kendimi hissetmiyorum Böyle aptal bir soru sordu :-) – andyuk

+1

Özel karakterler kaçmak için bazı yardımcı program var? –

+0

"her zaman garip davranışları önlemek için değişkenleri alıntı gerekir" - – Angelo

37

: için BASH açılımları tam açıklaması için

, bakın.

Genellikle bile bu sözdizimi ile

$ echo "$FOO" 

Ancak, ben yaşadım sorunların kullanmak. Aşağıdaki senaryoyu düşünün.

#!/bin/bash 
curl_opts="-s --noproxy * -O" 
curl $curl_opts "$1" 

* ihtiyaçları curl için aynen geçirilecek ancak aynı sorunlar ortaya çıkacaktır. Yukarıdaki örnek çalışmayacaktır (geçerli dizinde dosya isimlerine genişleyecektir) ve \*. $curl_opts için de teklif veremezsiniz, çünkü curl'a tek (geçersiz) bir seçenek olarak tanınır.

curl: option -s --noproxy * -O: is unknown 
curl: try 'curl --help' or 'curl --manual' for more information 

Bu nedenle küresel desen uygulandığında ise tamamen dosya genişlemesini önlemek için bash değişken $GLOBIGNORE kullanımını tavsiye veya kullanırsınız set -f yerleşik bayrak.

me$ FOO="BAR * BAR" 

me$ echo $FOO 
BAR file1 file2 file3 file4 BAR 

me$ set -f 
me$ echo $FOO 
BAR * BAR 

me$ set +f 
me$ GLOBIGNORE=* 
me$ echo $FOO 
BAR * BAR 
+2

Sadece "set -f" benim durumumda çalıştı –

+2

Harika bir açıklama, teşekkürler! Usecase'im 'SELECT * FROM etc.', bu Çalışmanın tek yolu – knutole

+0

Set -f çözümünü sunduğunuz için teşekkürler! – hachre

İlgili konular