Bash, dahili olarak boş baytlarla sonlandırılan C tarzı dizeleri kullanır. Bu, bir Bash dizesinin (örneğin bir değişkenin değeri veya bir komutun argümanı gibi) aslında boş bir bayt içeremeyeceği anlamına gelir. Örneğin, bu mini script:
foobar=$'foo\0bar' # foobar='foo' + null byte + 'bar'
echo "${#foobar}" # print length of $foobar
aslında yazdırır 3
, çünkü $foobar
aslında sadece 'foo'
: bar
dizgenin sonundan sonra gelir.
Benzer şekilde, echo $'foo\0bar'
sadece baskı yapar foo
, çünkü kısmı echo
bilmez \0bar
.
Gördüğünüz gibi, \0
sıra bir $'...'
stil dizesinde aslında çok yanıltıcıdır ; dize içinde boş bir bayt gibi görünüyor, ancak bu şekilde çalışma sonunda bitmiyor. İlk örneğinizde read
emrinizde var -d $'\0'
. Bu işe yarıyor, fakat -d ''
aynı zamanda işe yarıyor! (Yani bir açıkça belgelenmiş bir özellik değil read
, ama aynı nedenle çalışır varsayalım: ''
Boş dize, sonlandırıcı boş bayt hemen gelir böylece. "Nin ilk karakteri kullanılarak belgelenmiştir delim ", ben bile eserlerini tahmin "ilk karakter" dizenin sonundan sonraysa!)-d delim
Eğer bildiğimiz gibi Ama find
örneğin, o ise bir komut boş byte çıktısını ve bu bayt girdi olarak okur başka bir birliğe yöneltilen için mümkün müdür. Bunun hiçbir kısmı, Bash içindeki bir dizgede boş bir bayt depolamaya dayanmaz . İkinci örneğinizle ilgili tek sorun, $'\0'
bir komutun argümanında kullanamamız ; echo "$file"$'\0'
Sonunda boş byte'ı mutlu bir şekilde yazdırabilirdi.
Dolayısıyla kullanmak yerine, stil dizeleriyle aynı türde kaçış dizilerini destekleyen echo
kullanabilirsiniz . Bu şekilde, bir dize içinde boş bir bayta sahip olmak zorunda kalmadan boş bir bayt yazdırabilirsiniz. Bu şuna benzerdi:printf
$'...'
for file in * ; do printf '%s\0' "$file" ; done \
| while IFS= read -r -d '' ; do echo "$REPLY" ; done
ya da sadece bu:
printf '%s\0' * \
| while IFS= read -r -d '' ; do echo "$REPLY" ; done
(Not: echo
aslında boş bir baytı -e
işlemesine \0
ve yazdırmasına izin verecek bir bayrak da vardır ; ancak dosya adınızdaki herhangi bir özel diziyi işlemeye de çalışacaktır. Bu nedenle printf
yaklaşım daha sağlamdır.)
Bu arada, bazı kabukları vardır do boş iç dizeleri bayt izin verir. Örneğin, Zsh'de örneğin çalışır (varsayılan ayar varsayarak). Bununla birlikte, kabuğunuzdan bağımsız olarak, Unix benzeri işletim sistemleri programlara argümanların içine boş baytlar eklemek için bir yol sağlamaz (çünkü program argümanları C tarzı dizgiler olarak iletilir), bu nedenle her zaman bazı sınırlamalar olacaktır. Çünkü sadece (Sizin örnek Zsh çalışabilir echo
bir kabuk yerleşiğidir Zsh diğer programları çağırmak için OS desteğine güvenerek olmadan çağırmak, böylece. Eğer kullandıysanız command echo
yerine echo
, bu yerleşiğini atlanır ve bağımsız kullanıldığı böylece echo
programı $PATH
, Zsh'de aynı davranışı Bash ile aynı şekilde görürsünüz.)
-d ''
Sınırlandırmak için zaten bir araç varsa, IFS neden hiçbir şeye ayarlanmamış\0
? Burada bir açıklama buldum: stackoverflow.com/questions/8677546/…