@ Kusalananda'nın iyi cevabının üzerine fazladan bir not .
echo run after_bundle
iyidir çünkü bu 3 argümandaki karakterlerin hiçbiri echo
kabuğa özel karakterler içermez.
Ve (burada yapmak istediğim ekstra nokta), bu baytların kabuğa özel karakterlere çevirebileceği bir sistem yerel ayarı yok.
Tüm bu karakterler POSIX'in taşınabilir karakter setini çağırdığı karakterdedir . Bu karakterler bulunmalı ve POSIX sistemindeki tüm karakter kümelerinde aynı şekilde kodlanmalıdır²².
Böylece bu komut satırı, yerel ayardan bağımsız olarak aynı şekilde yorumlanacaktır.
Şimdi, bu taşınabilir karakter kümesinin dışındaki karakterleri kullanmaya başlarsak, kabuğa özel olmasalar bile bunları alıntılamak iyi bir fikirdir, çünkü başka bir yerde, onları oluşturan baytlar, farklı karakterler olarak yorumlanabilir kabuk için özel. İster echo
başka bir komut kullanıp kullanmadığınızı , sorunun echo
kabuğun kodunu nasıl ayrıştırdığı ile ilgili olduğunu unutmayın .
Örneğin bir UTF-8'de:
echo voilà | iconv -f UTF-8 -t //TRANSLIT
Bu à
0xc3 0xa0 olarak kodlanır. Şimdi, bir kabuk komut dosyasında bu kod satırına sahipseniz ve kabuk komut dosyası, karakteri UTF-8 olmayan bir yerel ayar kullanan bir kullanıcı tarafından çağrılırsa, bu iki bayt çok farklı karakterler oluşturabilir.
Örneğin, bir fr_FR.ISO8859-15
yerel ayarda, Fransızca dilini (İngilizce dahil çoğu batı Avrupa dili için kullanılanla aynı) kapsayan standart tek baytlık karakter kümesi kullanan tipik bir Fransız yerel ayarı, 0xc3 baytının Ã
karakter olarak ve 0xa0'ın boşluk karakteri.
Ve NetBSD³ gibi birkaç sistemde, bu kırılmayan boşluk boş bir karakter olarak kabul edilir ( isblank()
üzerinde doğru döner, eşleştirilir [[:blank:]]
) ve bash
bu nedenle kabukları sözdiziminde bir token sınırlayıcı olarak ele alır.
Çalışan yerine aracı That echo
ile $'voil\xc3\xa0'
argüman olarak, onlar ile çalıştırmak $'voil\xc3'
o baskı anlamına gelir argüman olarak voilà
doğru.
Bu kodlama ile aynı kodlama içeren birçok karakter BIG5, bıg5-HKSCS, GB18030, GBK gibi Çinli karakter setleri ile çok daha kötü olur |
, `
, \
Microsoft Kanji aka hariç (ayrıca o gülünç SJIS (en kötü isim) bunun ¥
yerine, çoğu araç tarafından 0x5c olarak kodlandığı için \
işlem görüyor \
).
Örneğin, bir zh_CN.gb18030
Çin yerel ayarındaysanız, aşağıdaki gibi bir komut dosyası yazarsınız:
echo 詜 reboot
Bu komut dosyası 詜 reboot
GB18030 veya GBK 唰 reboot
kullanan bir yerel ayarda, BIG5 veya BIG5-HKSCS kullanan bir yerel ayarda, ancak ASCII kullanan bir C yerel ayarında veya ISO8859-15 veya UTF-8 kullanan bir yerel ayarda reboot
, GB18030 kodlaması nedeniyle çalıştırılmasına neden olur arasında 詜
0xd4 0x7c ve 0x7c ait kodlama |
koşuyoruz sonunda böylece ASCII:
echo �| reboot
(bununla birlikte , 0xd4 baytının yerel ayarda oluşturulduğu anlamına gelir). uname
Bunun yerine daha az zararlı olanlara örnek reboot
:
$ echo $'echo \u8a5c uname' | iconv -t gb18030 > myscript
$ LC_ALL=zh_CN.gb18030 bash ./myscript | sed -n l
\324| uname$
$ LC_ALL=C bash ./myscript | sed -n l
Linux$
( uname
çalıştırıldı).
Bu yüzden tavsiyem, taşınabilir karakter kümesinin dışında karakter içeren tüm dizeleri alıntılamak olacaktır.
Ancak kodlaması beri unutmayın \
ve `
bu karakterlerin bazılarının kodlama bulunur, bu kullanımda daha iyi değil \
ya "..."
ya $'...'
(iç `
ve / veya \
hala özeldir), ancak '...'
bunun yerine taşınabilir karakter kümesi dışında karakterleri alıntı.
Charset '
kodlama kodlama içeren herhangi bir karakter ( tabii ki kendisi dışında) herhangi bir karakteri olan herhangi bir sistem farkında değilim '
, bu yüzden bu '...'
kesinlikle en güvenli olmalıdır.
Birkaç kabuğun $'\uXXXX'
, Unicode kod noktalarına göre karakterleri ifade etmek için bir gösterimi de desteklediğini unutmayın . Gibi kabukları içinde zsh
ve bash
(yani charset o karakteri yoksa beklenmedik davranışlar neden olabilir gerçi) karakteri yerelin charset kodlanmış eklenir. Bu, kabuk kodunuza ASCII olmayan karakterler eklemekten kaçınmanızı sağlar.
Yukarıda:
echo 'voilà' | iconv -f UTF-8 -t //TRANSLIT
echo '詜 reboot'
Veya:
echo $'voil\u00e0'
echo $'\u8a5c reboot'
(uyarıyla, bu karakterleri olmayan yerel bölgelerde çalıştırıldığında komut dosyasını kırabilir).
Ya da daha iyisi, \
aynı zamanda echo
(ya da en azından bazı echo
uygulamalar, en azından Unix uyumlu olanları) özel olduğu için:
printf '%s\n' 'voilà' | iconv -f UTF-8 -t //TRANSLIT
printf '%s\n' '詜 reboot'
( \
ilk argümanında da özel olduğunu unutmayın printf
, bu nedenle ASCII olmayan karakterlerin kodlamasını içerebilmeleri durumunda da bundan daha iyi kaçınılmalıdır \
).
Şunları da yapabileceğinizi unutmayın:
'echo' 'voilà' | 'iconv' '-f' 'UTF-8' '-t' '//TRANSLIT'
(aşırıya kaçabilir ama taşınabilir karakter setinde hangi karakterlerin olduğundan emin değilseniz size biraz huzur verebilir)
Ayrıca, eski `...`
bir komut değiştirme şekli (başka bir ters eğik çizgi işleme düzeyi tanıtır) kullanmadığınızdan emin olun , $(...)
bunun yerine kullanın.
¹ teknik olarak echo
da argüman olarak geçirilen echo
fayda (o çağrılan nasıl anlatmamız), bu kadar argv[0]
ve argc
en kabuklarda günümüzde bile, 3'tür echo
yerleşik olduğu böylece, exec()
a /bin/echo
simüle edilir 3 bağımsız değişkenler listesi ile dosyanın kabuk. Ayrıca, argümanların listesini ikinciden ( argv[1]
to argv[argc - 1]
) başlayarak düşünmek yaygındır, çünkü komutların esas olarak hareket ettiği budur.
² ja_JP.SJIS
Karakterleri \
veya ~
karakterleri olmayan FreeBSD sistemlerinin gülünç yeri olmasının dikkate değer bir istisnası !
Systems birçok sistem (FreeBSD, Solaris, GNU değil) UF + 8A0'ı [[:blank:]]
UTF-8 yerel ayarlarında olarak görürken , bu tür sorunlardan kaçınmak için ISO8859-15 kullananlar gibi diğer yerel ortamlarda çok azının çalıştığını unutmayın .