@ Kusalananda'nın iyi cevabının üzerine fazladan bir not .
echo run after_bundle
iyidir çünkü bu 3 argümandaki karakterlerin hiçbiri echokabuğ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 echobaşka bir komut kullanıp kullanmadığınızı , sorunun echokabuğ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-15yerel 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 bashbu nedenle kabukları sözdiziminde bir token sınırlayıcı olarak ele alır.
Çalışan yerine aracı That echoile $'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ı 詜 rebootGB18030 veya GBK 唰 rebootkullanan 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). unameBunun 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 zshve 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 echoda argüman olarak geçirilen echofayda (o çağrılan nasıl anlatmamız), bu kadar argv[0]ve argcen kabuklarda günümüzde bile, 3'tür echoyerleşik olduğu böylece, exec()a /bin/echosimü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.SJISKarakterleri \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 .