Yanıtlar:
KISA CEVAP
Diğerlerinin söylediği gibi - garip davranışı önlemek için her zaman değişkenleri alıntılamanız gerekir. Kullanım Yani "$ foo" echo yerine sadece $ foo echo .
UZUN CEVAP
Bence bu örnek daha fazla açıklamayı gerektiriyor, çünkü yüzünde göründüğünden daha fazlası var.
Karışıklıklarınızın nereye geldiğini görebiliyorum çünkü ilk örneğinizi çalıştırdıktan sonra muhtemelen kendinize kabuğun açıkça yaptığını düşündünüz:
İlk örneğinizden:
me$ FOO="BAR * BAR"
me$ echo $FOO
Parametre genişletmeden sonra:
me$ echo BAR * BAR
Ve dosya adı genişletmesinden sonra:
me$ echo BAR file1 file2 file3 file4 BAR
Ve sadece echo BAR * BAR
komut satırına yazarsanız, bunların eşdeğer olduğunu görürsünüz.
Muhtemelen kendinize "* 'dan kaçarsam, dosya adının genişletilmesini önleyebilirim" diye düşündünüz.
İkinci örneğinizden:
me$ FOO="BAR \* BAR"
me$ echo $FOO
Parametre genişletmeden sonra:
me$ echo BAR \* BAR
Ve dosya adı genişletmesinden sonra:
me$ echo BAR \* BAR
Doğrudan komut satırına "echo BAR \ * BAR" yazmayı denerseniz, gerçekten de "BAR * BAR" yazılır çünkü dosya adı genişletmesi kaçış tarafından önlenir.
Peki neden $ foo kullanmak işe yaramadı?
Çünkü üçüncü bir genişleme var - Alıntı Kaldırma. Bash manuel teklif kaldırma:
Önceki genişletmelerden sonra, yukarıdaki genişletmelerden birinden kaynaklanmayan '\', '' 've' "'karakterlerinin alıntılanmamış tüm oluşumları kaldırılır.
Yani komutu doğrudan komut satırına yazdığınızda kaçış karakteri önceki bir genişletmenin sonucu değildir, bu yüzden BASH echo komutuna göndermeden önce onu kaldırır, ancak 2. örnekte "\ *" önceki bir Parametre genişletmesinin sonucu, bu yüzden kaldırılmaz. Sonuç olarak, echo "\ *" alır ve yazdırdığı şey budur.
İlk örnek - "*" arasındaki farkın Alıntı Kaldırma ile kaldırılacak karakterlere dahil olmadığını unutmayın.
Umarım bu mantıklı gelir. Sonunda sonuç aynı - sadece tırnak kullanın. Sadece Parametre ve Dosya adı genişletmesi oyundaysa mantıklı bir şekilde çalışması gereken neden kaçmayı açıklayacağımı düşündüm.
BASH genişletmelerinin tam açıklaması için bakınız:
http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions
Bu eski konuya biraz ekleyeceğim.
Genellikle
$ echo "$FOO"
Ancak, bu sözdiziminde bile sorun yaşadım. Aşağıdaki komut dosyasını düşünün.
#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"
*
İhtiyaçlar için aynen geçirilecek curl
ancak aynı sorunlar ortaya çıkacaktır. Yukarıdaki örnek çalışmaz (geçerli dizindeki dosya adlarına genişler) ve ikisi de çalışmaz \*
. Ayrıca $curl_opts
tek bir (geçersiz) seçenek olarak tanınacağı için teklif veremezsiniz curl
.
curl: option -s --noproxy * -O: is unknown
curl: try 'curl --help' or 'curl --manual' for more information
Bu nedenle , global kalıba uygulanırsa dosya adının genişletilmesini tamamen önlemek için bash
değişkenin $GLOBIGNORE
kullanılmasını veya set -f
yerleşik bayrağı kullanmasını öneririm .
#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1" ## no filename expansion
Orijinal örneğinize başvurma:
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
SELECT * FROM etc.
, çalışan tek yol budur.
echo "$FOO"
Komut satırından printf
ziyade kullanma alışkanlığına girmeye değer olabilir echo
.
Bu örnekte fazla fayda sağlamaz, ancak daha karmaşık çıktılar için daha yararlı olabilir.
FOO="BAR * BAR"
printf %s "$FOO"