बिट्स की पाठ फ़ाइल को बाइनरी फ़ाइल में बदलें


12

मेरे पास instructions.txtसामग्री के साथ एक फ़ाइल है :

00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

मैं instructions.binउसी डेटा की बाइनरी फ़ाइल कैसे बना सकता हूं instructions.txt। दूसरे शब्दों में .binफ़ाइल समान 192 बिट्स होनी चाहिए जो .txtफ़ाइल में 32 बिट्स प्रति पंक्ति के साथ हो। मैं उबंटू लिनक्स पर बैश का उपयोग कर रहा हूं। मैं उपयोग करने की कोशिश कर रहा था, xxd -b instructions.txtलेकिन आउटपुट 192 बिट्स से अधिक लंबा है।

जवाबों:


6

oneliner 32-बिट स्ट्रिंग्स को बदलने और शून्य में संगत बाइनरी में बदलने के लिए:

$ perl -ne 'print pack("B32", $_)' < instructions.txt > instructions.bin

यह क्या करता है:

  • perl -neSTDIN ( instructions.txt) पर प्रदान की गई इनपुट फ़ाइल की प्रत्येक पंक्ति के माध्यम से पुनरावृति करेगा
  • pack("B32", $_)32 बिट्स ( $_जिसे हम सिर्फ STDIN से पढ़ते हैं) की एक स्ट्रिंग सूची लेंगे , और इसे बाइनरी वैल्यू में परिवर्तित करेंगे ( "b32"यदि आप वैकल्पिक रूप से उपयोग कर सकते हैं यदि आप बिट ऑर्डर के बजाय प्रत्येक बाइट के अंदर आरोही बिट ऑर्डर चाहते थे, तो perldoc -f packअधिक विवरण देखें)
  • print फिर उस मूल्य को STDOUT में परिवर्तित कर देगा, जिसे हम तब अपनी बाइनरी फ़ाइल में रीडायरेक्ट करते हैं instructions.bin

सत्यापित करें:

$ hexdump -Cv instructions.bin
00000000  00 00 00 13 02 d1 20 83  00 73 02 b3 00 73 04 33  |...... ..s...s.3|
00000010  00 73 64 b3 00 00 00 13                           |.sd.....|
00000018

$ xxd -b -c4 instructions.bin
00000000: 00000000 00000000 00000000 00010011  ....
00000004: 00000010 11010001 00100000 10000011  .. .
00000008: 00000000 01110011 00000010 10110011  .s..
0000000c: 00000000 01110011 00000100 00110011  .s.3
00000010: 00000000 01110011 01100100 10110011  .sd.
00000014: 00000000 00000000 00000000 00010011  ....

8

-rविकल्प (रिवर्स मोड) को जोड़ना xxd -bवास्तव में उद्देश्य के रूप में काम नहीं करता है, क्योंकि xxd बस इन दो झंडों के संयोजन का समर्थन नहीं करता है (यह अनदेखा करता है -bयदि दोनों दिए गए हैं)। इसके बजाय, आपको पहले खुद को बिट्स को हेक्स में बदलना होगा। इस तरह के उदाहरण के लिए:

( echo 'obase=16;ibase=2'; sed -Ee 's/[01]{4}/;\0/g' instructions.txt ) | bc | xxd -r -p > instructions.bin

पूर्ण विवरण:

  • कोष्ठकों के अंदर का भाग एक bcस्क्रिप्ट बनाता है । यह पहले इनपुट बेस को बाइनरी (2) और आउटपुट बेस को हेक्साडेसिमल (16) में सेट करता है। उसके बाद, sedकमांड instructions.txt4 बिट्स के प्रत्येक समूह के बीच एक अर्धविराम के साथ सामग्री को प्रिंट करता है , जो 1 हेक्स अंकों से मेल खाती है। परिणाम में पाइप किया जाता है bc
  • अर्धविराम में एक कमांड विभाजक है bc, इसलिए सभी स्क्रिप्ट करता है हर इनपुट पूर्णांक को वापस प्रिंट करें (आधार रूपांतरण के बाद)।
  • का आउटपुट bcहेक्स अंकों का एक क्रम है, जिसे सामान्य रूप से फ़ाइल में परिवर्तित किया जा सकता है xxd -r -p

आउटपुट:

$ hexdump -Cv instructions.bin
00000000  00 00 00 13 02 d1 20 83  00 73 02 b3 00 73 04 33  |...... ..s...s.3|
00000010  00 73 64 b3 00 00 00 13                           |.sd.....|
00000018
$ xxd -b -c4 instructions.bin
00000000: 00000000 00000000 00000000 00010011  ....
00000004: 00000010 11010001 00100000 10000011  .. .
00000008: 00000000 01110011 00000010 10110011  .s..
0000000c: 00000000 01110011 00000100 00110011  .s.3
00000010: 00000000 01110011 01100100 10110011  .sd.
00000014: 00000000 00000000 00000000 00010011  ....

क्षमा करें, इसमें अभी भी एक एंडियननेस बग है। इसे ठीक करने पर काम चल रहा है!
खानाबदोश

1
वास्तव में, यह ठीक है। मैं पिछले xxd कमांड में गलत आउटपुट चौड़ाई का उपयोग करके पहले उलझन में था।
खानाबदोश

1
मैंने स्क्रिप्ट का परीक्षण किया है और यह काम करता है लेकिन आउटपुट (standard_in) 1: syntax error:। क्या आप बता सकते हैं कि syntax errorयह क्या है या ऐसा क्यों होता है? क्या आपके मशीन पर भी ऐसा होता है?
dopamane

2

मेरे मूल जवाब गलत था - xxdया तो स्वीकार नहीं कर सकते -pया -rके साथ -b...

यह देखते हुए कि अन्य उत्तर व्यावहारिक हैं, और " दूसरे तरीके " के हित में, निम्नलिखित के बारे में कैसे:

इनपुट

$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

उत्पादन

$ hexdump -Cv < instructions.bin
00000000  00 00 00 13 02 d1 20 83  00 73 02 b3 00 73 04 33  |...... ..s...s.3|
00000010  00 73 64 b3 00 00 00 13                           |.sd.....|
00000018

बैश पाइपलाइन:

cat instructions.txt \
    | tr -d $'\n' \
    | while read -N 4 nibble; do 
        printf '%x' "$((2#${nibble}))"; \
      done \
    | xxd -r -p \
    > instructions.bin
  • cat - अनावश्यक, लेकिन स्पष्टता के लिए उपयोग किया जाता है
  • tr -d $'\n' - इनपुट से सभी newlines निकालें
  • read -N 4 nibble- पढ़ वास्तव में 4 × पात्रों nibbleचर
  • printf '%x' "$((2#${nibble}))" बाइनरी से 1 × हेक्स चरित्र में बड़प्पन को परिवर्तित करें
    • $((2#...)) - दिए गए मान को बेस 2 (बाइनरी) से बेस 10 (दशमलव) में बदलें
    • printf '%x' - दिए गए मान को आधार 10 (दशमलव) से आधार 16 (हेक्साडेसिमल) में स्वरूपित करें
  • xxd -r -p- रिवर्स ( -r) एक सादे डंप ( -p) - हेक्साडेसिमल से कच्चे बाइनरी तक

अजगर:

python << EOF > instructions.bin
d = '$(cat instructions.txt | tr -d $'\n')'
print(''.join([chr(int(d[i:i+8],2)) for i in range(0, len(d), 8)]))
EOF
  • पाइथॉन<< EOF कोड में सामग्री प्राप्त करने के लिए एक अनअकॉटेड हेरेडोक ( ) का उपयोग किया जाता है
    • यदि इनपुट बड़ा हो जाता है तो यह कुशल नहीं है
  • catऔर tr- एक स्वच्छ (एक-पंक्ति) इनपुट प्राप्त करने के लिए उपयोग किया जाता है
  • range(0, len(d), 8)- dएक समय में 8 × वर्णों को बढ़ाते हुए, स्ट्रिंग के 0 से अंत तक की संख्या की सूची प्राप्त करें ।
  • chr(int(d[i:i+8],2))- d[i:i+8]बाइनरी से दशमलव ( int(..., 2)), और फिर एक कच्चे चरित्र ( chr(...)) के लिए वर्तमान टुकड़ा ( ) में परिवर्तित करें
  • [ x for y in z]- सूची समझ
  • ''.join(...) - पात्रों की सूची को एक स्ट्रिंग में परिवर्तित करें
  • print(...) - इसे छापो

1
नोट: |एक पंक्ति के अंत में कई गोले बैकस्लैश की तरह काम करते हैं: कमांड अगली पंक्ति तक जारी रहती है। इस तरह आप कुछ बैकस्लैश से छुटकारा पा सकते हैं। मुझे यकीन नहीं है कि एलएफ के बाद पाइप प्रतीकों का उपयोग करना आपका सूचित निर्णय था। यदि आप नहीं जानते हैं तो मैं दूसरे तरीके का उल्लेख कर रहा हूं।
कामिल मैकियोरोस्की

1
मुझे नहीं पता था, धन्यवाद! मैं पाइपलाइन को तार्किक लाइनों में तोड़ना पसंद करता हूं, और दृश्यता / स्पष्टता के लिए पाइप |(या पुनर्निर्देशन >, बूलियन ऑपरेटर &&, आदि ...) को स्पष्ट रूप से सामने रखता है ... शायद एक शैलीगत / पसंद की चीज।
Attie

1
कुछ विचारों के बाद मैं इस शैली का उपयोग करना शुरू कर सकता हूं क्योंकि कोई भी बता सकता है कि दो लाइनें जुड़ी हुई हैं, उनमें से किसी की भी जांच करके । यदि |अंत में है, तो अगली पंक्ति एक स्टैंडअलोन कमांड की तरह दिख सकती है, यह भ्रामक हो सकती है। यही कारण है कि मुझे लगा कि शैली आपके द्वारा सूचित निर्णय हो सकती है।
कामिल मैकियोरोस्की

बहुत बढ़िया, मुझे पता है कि यह कैसे जाता है :-)
एट्टी


1

आप कोडगॉल्फ एसई साइट पर इसे पोस्ट करने की कोशिश कर सकते हैं, लेकिन यहां मेरा वैकल्पिक पायथन संस्करण है (सिर्फ किक चुनौती के लिए):

python -c "import sys,struct;[sys.stdout.buffer.write(struct.pack('!i',int(x,2)))for x in sys.stdin]" \
< input.txt > output.bin

मान लें कि input.txtआपका डेटा शामिल है, और इसे 32 वर्ण प्रति पंक्ति पर स्वरूपित किया गया है।

यह पायथन 3 structपैकेज और स्टाइन / आउट को लिखने / पढ़ने का उपयोग करता है। (अजगर 2 में यह छोटा होता)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.