bash değişkeni 0x00 değişkenini saklayamaz


11

Ben dd ile bazı hile yapmaya çalışıyorum. Ben dd içine boru için "başlık" adlı bir değişkende bazı hexvalues ​​saklamak mümkün olacağını düşündüm.

Değişken olmadan ilk adım şuydu:

$ echo -ne "\x36\xc9\xda\x00\xb4" |dd of=hex
$ hd hex

00000000  36 c9 da 00 b4                                    |6....|
00000005

Bundan sonra bunu denedim:

$ header=$(echo -ne "\x36\xc9\xda\x00\xb4") 
$ echo -n $header | hd

00000000  36 c9 da b4                                       |6...|
00000004

Gördüğünüz gibi değişken \x00içindeki değerimi kaybettim $header. Herkes bu davranış için bir açıklaması var mı? Bu beni delirtiyor.


Anladım bash: warning: command substitution: ignored null byte in input.
Kusalananda

Tırnaklar eksik, header="$(echo -ne "\x36\xc9\xda\x00\xb4")"; echo -n "$header" | hdancak bu sadece aynı sonucu verir.
ctrl-alt-delor

Bu işe yarıyor header="\x36\xc9\xda\x00\xb4"; echo -n "$header" | hdama insan tarafından okunabilir formu saklamakla aynı şey değil.
ctrl-alt-delor

Yanıtlar:


16

Boş bir baytı bir dizede saklayamazsınız çünkü Bash, boş baytı sonlandırıcılar için ayıran C stili dizeleri kullanır. Bu nedenle, Bash'i ortada saklamak zorunda kalmadan, boş byte içeren diziyi borulamak için komut dosyanızı yeniden yazmanız gerekir. Örneğin, bunu yapabilirsiniz:

printf "\x36\xc9\xda\x00\xb4" | hd

Bu arada, ihtiyacınız olmadığına dikkat edin echo; Bunun için Bash'leri kullanabilirsiniz printf.

Veya zincirlemek yerine geçici bir dosya kullanabilirsiniz:

printf "\x36\xc9\xda\x00\xb4" > /tmp/mysequence
hd /tmp/mysequence

Tabii ki, bu dosyanın /tmp/mysequencezaten mevcut olması sorunu var. Ve şimdi geçici dosyalar oluşturmaya ve yollarını dizelere kaydetmeye devam etmelisiniz.

Veya işlem ikamesi kullanarak bunu önleyebilirsiniz:

hd <(printf "\x36\xc9\xda\x00\xb4")

<(command)Operatör çıktısını alacak dosya sisteminde bir adlandırılmış yöneltme oluşturur command. hdilk argümanı olarak, neredeyse her dosya gibi açılacağı ve okunacağı boruya giden yolu alacaktır . Bununla ilgili daha fazla bilgiyi buradan edinebilirsiniz: https://unix.stackexchange.com/a/17117/136742 .


1
Doğru olsa da, bu kesin bir neden değil, bir uygulama detayıdır. Ona baktım ve POSIX standardı aslında bu davranışı gerektiriyor , bu yüzden gerçek nedeniniz var. (Bazılarının belirttiği gibi, zshbunu yapacak, ama sadece nōn-POSIX modunda.) Aslında içine baktım çünkü bunu uygulamaya değip değmeyeceğini merak ediyordum mksh
mirabilos

@mirabilos, bunu genişletmek ister misin? Çıkış boş karakteri vardır ve POSIX modunda zsh için, aklıma gelen tek anlamlı farkın o zaman AFAICT davranış komut ikamesi için POSIX başına belirtilmemiş olan shöykünme, \0varsayılan değer değildir $IFS. echo "$(printf 'a\0b')"Hala Tamam çalışır shiçinde öykünme zsh.
Stéphane Chazelas

3
kabukları daha on tarafından POSIX standardını öncedir ya düşünülürse @mirabilos, ben tahmin gerçek olduğunu bulmak olabilir fiili nedeni kabukları C tarzı dizeleri kullanılan ve standart olduğu etrafında inşa edilmiş olmasıdır.
giusti

Ekoya karşı printf hakkında ayrıntılı tartışma için iyi bir Q buldum. unix.stackexchange.com/questions/65803/…
Paulb

8

Bunun zshyerine, NUL karakterini değişkenlerinde saklayabilen tek kabuk olan kullanabilirsiniz. Bu karakter bile varsayılan değeri olur $IFSiçinde zsh.

nul=$'\0'

Veya:

nul=$'\x0'

Veya

nul=$'\u0000'

Veya

nul=$(printf '\0')

Ancak bir komuta bir argüman veya ortam değişkeni gibi bir değişken geçemez unutmayın idam geçirilen NUL ayrılmış dizeleri argümanları ve ortam değişkenleri gibidir execve()sistem çağrısı (sistemin API bir sınırlama değil, kabuk ). Ancak zsh, NUL baytlarını işlevlere veya yerleşik komutlara argüman olarak iletebilirsiniz.

echo $'\0' # works
/bin/echo $'\0' # doesn't

1
Msgstr "Bunun yerine zsh kullanabilirsiniz". Hayır teşekkürler - Kendime şu anda yeni başlayanlar olarak bash komut dosyası öğretiyorum. Kendimi başka bir sözdizimi ile karıştırmak istemiyorum. Ama önerdiğin için çok teşekkür ederim
Frank

Nitekim zshsorunuzda sözdizimi kullandınız . echo -n $headeriçeriğini geçmesi anlamına $headeriçin bir son bağımsız değişken olarak değişken echo -nolduğunu zsh(ya da fishya da rcya da es) sözdizimi değil, bash sözdizimi. İçinde bash, bunun çok farklı bir anlamı var . Daha genel zsholarak ksh( bashGNU kabuğu, kshUnix de-facto kabuğunun kısmen veya daha az bir parçası olarak ) gibidir, ancak Bourne kabuğunun tasarım özelliklerinin çoğu sabittir (ve birçok ekstra özellik ve çok daha kullanıcı dostu / daha az şaşırtıcı).
Stéphane Chazelas

Dikkatli olun: zsh bazen sıfır baytı değiştirebilir: echo $(printf 'ab\0cd') | od -vAn -tx1c `61 62 20 63 64 0a` yazdırır, bu bir NUL olması gereken bir alandır.
Isaac

1
Ve bu başka hiçbir şeyin (hiçbiri, sıfır) kabuğunun çoğalmayacağı bir şey. Bu bir betiğin zsh içinde çok özel bir şekilde davranmasını sağlar. Kanımca: zsh sadece çok zeki olmaya çalışıyor.
Isaac

2
POSIX sh standardında zsh betikleri yazmaya alışık olan tasarım yanlışlıklarını "düzeltmek", başka herhangi bir kabukta kullanıldığında buggy olacak uygulamalara alışmak anlamına gelir. Bu, sözdiziminde böyle bir sorun değil, farklı bir dilden çok farklı.
Charles Duffy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.