बैश हेक्वेले को 0x00 वेरिएबल में स्टोर नहीं कर सकता है


11

मैं dd के साथ कुछ ट्रिक्स करने की कोशिश कर रहा हूँ। मुझे लगा कि इसे dd में पाइप करने के लिए "हेडर" नामक वैरिएबल में कुछ हेक्सवेल्यूज़ को स्टोर करना संभव होगा।

एक चर के बिना मेरा पहला कदम यह था:

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

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

उसके बाद मैंने यह कोशिश की:

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

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

जैसा कि आप देख सकते हैं कि मैंने चर \x00में अपना मूल्य खो दिया है $header। क्या किसी के पास इस व्यवहार के लिए स्पष्टीकरण है? यह मुझे पागल बना रहा है।


मुझे मिलता है bash: warning: command substitution: ignored null byte in input
Kusalananda

आप उद्धरण याद कर रहे हैं, header="$(echo -ne "\x36\xc9\xda\x00\xb4")"; echo -n "$header" | hdलेकिन यह सिर्फ एक ही परिणाम देता है होना चाहिए ।
ctrl-alt-delor

यह काम करता है header="\x36\xc9\xda\x00\xb4"; echo -n "$header" | hd, लेकिन यह एक ही चीज नहीं है क्योंकि यह मानव के पठनीय रूप को संग्रहीत कर रहा है।
ctrl-alt-delor 19

जवाबों:


16

आप एक स्ट्रिंग में एक अशक्त बाइट को स्टोर नहीं कर सकते क्योंकि बैश सी-स्टाइल स्ट्रिंग्स का उपयोग करता है, जो टर्मिनेटर के लिए नल बाइट को आरक्षित करता है। इसलिए आपको अपनी स्क्रिप्ट को बस उस अनुक्रम को फिर से लिखने की आवश्यकता है जिसमें बश के बिना नल बाइट शामिल है, इसे बीच में स्टोर करने की आवश्यकता नहीं है। उदाहरण के लिए, आप यह कर सकते हैं:

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

ध्यान दें, वैसे, जिसकी आपको आवश्यकता नहीं है echo; आप इसके लिए printfकई अन्य सरल कार्यों के लिए बैश का उपयोग कर सकते हैं ।

या जंजीर के बजाय, आप एक अस्थायी फ़ाइल का उपयोग कर सकते हैं:

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

बेशक, यह समस्या है कि फ़ाइल /tmp/mysequenceपहले से मौजूद हो सकती है। और अब आपको अस्थायी फ़ाइलों को बनाने और उनके पथ को तार में सहेजने की आवश्यकता है।

या आप प्रक्रिया प्रतिस्थापन का उपयोग करके इससे बच सकते हैं:

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

<(command)ऑपरेटर फाइल सिस्टम में एक नामित पाइप, जिनमें से उत्पादन प्राप्त होगा बनाता है commandhdप्राप्त होगा, इसके पहले तर्क के रूप में, उस पाइप का पथ - जिसे वह खोल देगा और लगभग किसी भी फ़ाइल की तरह पढ़ जाएगा । आप यहाँ इसके बारे में अधिक पढ़ सकते हैं: /unix//a/17117/136742


1
सही होने के दौरान, यह एक कार्यान्वयन विवरण है और सटीक कारण नहीं है। मैंने इसे देखा, और पोसिक्स मानक को वास्तव में इस व्यवहार की आवश्यकता है, इसलिए आपके पास वास्तविक कारण है। (जैसा कि कुछ ने बताया है, zshयह करेंगे, लेकिन केवल n Pn-POSIX मोड में।) मैंने वास्तव में इसे देखा क्योंकि मैं सोच रहा था कि क्या यह इसे लागू करने के लायक था mksh...
mirabilos

@mirabilos, क्या आप उस पर विस्तार करना चाहेंगे? AFAICT, कमांड के प्रतिस्थापन के लिए POSIX के अनुसार व्यवहार अनिर्दिष्ट होता है जब आउटपुट में NUL वर्ण होते हैं, और POSIX मोड में zsh के लिए, एकमात्र प्रासंगिक अंतर जो मैं सोच सकता हूं वह यह है कि shअनुकरण \0में, डिफ़ॉल्ट मान में नहीं है $IFSecho "$(printf 'a\0b')"अभी भी shअनुकरण में ठीक काम करता है zsh
स्टीफन चेज़लस

3
@mirabilos यह देखते हुए कि गोले एक दशक या उससे अधिक समय से POSIX मानक से पहले हैं, मुझे लगता है कि आप यह पता लगा सकते हैं कि वास्तविक वास्तविक कारण यह है कि गोले सी-स्टाइल स्ट्रिंग्स का उपयोग करते थे और मानक उसी के आसपास बनाया गया था।
जियुति

मुझे प्रिंटफ़ बनाम इको पर विस्तृत चर्चा के लिए एक अच्छा क्यू मिला। unix.stackexchange.com/questions/65803/…
पॉल

8

आप zshइसके बजाय उपयोग कर सकते हैं जो एकमात्र शेल है जो एनयूएल चरित्र को अपने चर में संग्रहीत कर सकता है। उस चरित्र का डिफ़ॉल्ट मान में होना भी होता $IFSहै zsh

nul=$'\0'

या:

nul=$'\x0'

या

nul=$'\u0000'

या

nul=$(printf '\0')

हालांकि ध्यान दें कि आप इस तरह के एक चर को एक तर्क या पर्यावरण चर के रूप में एक कमांड के लिए पारित नहीं कर सकते हैं जिसे तर्कों और पर्यावरण चर के रूप में निष्पादित किया जाता है NUL- सीमांकित तार को execve()सिस्टम कॉल (सिस्टम की एपीआई की एक सीमा, शेल नहीं) पर पारित किया जाता है )। में zsh, आप फिर भी पारित कर सकते हैं NUL कार्यों के लिए या आदेशों अंतर्निहित तर्क के रूप में बाइट्स।

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

1
"आप इसके बजाय zsh का उपयोग कर सकते हैं"। कोई धन्यवाद नहीं - मैं अभी शुरुआत के रूप में खुद को बैश-स्क्रिप्टिंग सिखा रहा हूं। मैं खुद को एक अन्य वाक्य रचना के साथ भ्रमित नहीं करना चाहता। लेकिन सुझाव देने के लिए आपका बहुत-बहुत धन्यवाद
फ्रैंक

तथ्य की बात के रूप में, आपने zshअपने प्रश्न में वाक्य रचना का उपयोग किया । अंतिम तर्क के रूप echo -n $headerमें $headerचर की सामग्री को पास करने के echo -nलिए zsh( fishया rcया es) सिंटैक्स है, न कि bash सिंटैक्स। में bash, इसका एक बहुत ही अलग अर्थ है । आम तौर पर ( zshजैसे , GNU शेल, कमोबेश एक हिस्सा-क्लोन , यूनिक्स डी-फैक्टो शेल) है, लेकिन बॉर्न शेल के अधिकांश डिजाइन आइडियोसिंक्रिसेस के साथ तय किए गए हैं (और बहुत सारी अतिरिक्त सुविधाएँ, और बहुत कुछ) अधिक उपयोगकर्ता के अनुकूल / कम आश्चर्यजनक)। kshbashksh
स्टीफन चेज़लस 20

सावधान रहें: zsh कभी-कभी एक शून्य बाइट बदल सकता है: echo $(printf 'ab\0cd') | od -vAn -tx1c `61 62 20 63 64 0a` प्रिंट करता है, यह एक ऐसा स्थान है जहां एक NUL मौजूद होना चाहिए।
इसहाक

1
और वह कुछ और नहीं (कोई नहीं, नील) खोल है। यह एक स्क्रिप्ट को zsh में बहुत ही खास तरीके से व्यवहार करता है। मेरी राय में: zsh बहुत चालाक बनने की कोशिश कर रहा है।
इसहाक

2
POSIX श मानक में मौजूद "डिज़ाइन" को मिसफिट करने से जो कि zsh स्क्रिप्ट लिखने के आदी हो रहे हैं, इसका मतलब है कि वे उन प्रथाओं के आदी हो रहे हैं जो किसी भी अन्य शेल में अभ्यास किए जाने पर छोटी गाड़ी होगी। यह एक वाक्यविन्यास के साथ ऐसी समस्या नहीं है जो एक अलग भाषा के विपरीत है ताकि कौशल या आदतों को स्थानांतरित करने की संभावना न हो, लेकिन ऐसा मामला हाथ में नहीं है।
चार्ल्स डफी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.