비트의 텍스트 파일을 이진 파일로 변환


12

instructions.txt내용이 담긴 파일 이 있습니다.

00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

instructions.bin와 동일한 데이터 의 이진 파일 을 어떻게 만들 수 있습니까 instructions.txt? 즉, .bin파일은 파일에있는 192 비트 .txt와 줄당 32 비트 여야합니다 . 우분투 리눅스에서 bash를 사용하고 있습니다. 사용하려고 xxd -b instructions.txt했지만 출력이 192 비트보다 깁니다.

답변:


6

one 및 0의 32 비트 문자열을 해당 바이너리로 변환하는 oneliner :

$ 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

xxd는 단순히이 두 플래그의 결합을 지원하지 않기 때문에 -r옵션 (역 모드)을 추가하면 xxd -b실제로 의도 한대로 작동하지 않습니다 -b. 대신 비트를 16 진수로 먼저 변환해야합니다. 예를 들면 다음과 같습니다.

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

전체 설명 :

  • 괄호 안의 부분은 bc스크립트를 만듭니다 . 먼저 입력 기준을 이진 (2)으로 설정하고 출력 기준을 16 진 (16)으로 설정합니다. 그 후,이 sed명령 instructions.txt은 4 비트의 각 그룹 사이에 세미콜론으로 내용을 인쇄합니다 . 이는 1 개의 16 진수에 해당합니다. 결과는로 파이프됩니다 bc.
  • 세미콜론은의 명령 구분 기호 bc이므로 모든 스크립트는 모든 입력 정수를 다시 출력합니다 (기본 변환 후).
  • 의 출력은 bc일련의 16 진 숫자이며 평소와 함께 파일로 변환 될 수 있습니다 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  ....

죄송합니다. 아직 엔디안 버그가 있습니다. 그것을 고치기 위해 노력하고 있습니다!
nomadictype

1
실제로는 괜찮습니다. 마지막 xxd 명령에서 잘못된 출력 너비를 사용하여 이전에 혼란 스러웠습니다.
nomadictype

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' -입력에서 모든 줄 바꿈을 제거하십시오.
  • read -N 4 nibble- 정확히 4x 문자를 nibble변수 로 읽습니다.
  • printf '%x' "$((2#${nibble}))" 니블을 이진수에서 1 × 16 진수 문자로 변환
    • $((2#...)) -주어진 값을 기수 2 (2 진)에서 기수 10 (10 진)으로 변환
    • printf '%x' -주어진 값을 10 진수 10 진수에서 16 진수 16 진수로 지정
  • xxd -r -p-16 진에서 원시 이진 -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
  • 인용 부호가없는 heredoc ( << EOF)을 사용하여 콘텐츠를 Python 코드로 가져옵니다.
    • 입력이 커지면 효율적이지 않습니다
  • cat그리고 tr-깨끗한 (한 줄) 입력을 얻는 데 사용됩니다.
  • range(0, len(d), 8)-0에서 문자열 끝까지의 숫자 목록을 가져와 한 번 d에 8x 문자 씩 밟습니다.
  • chr(int(d[i:i+8],2))-현재 슬라이스 ( d[i:i+8])를 이진수에서 십진수 ( int(..., 2)) 로 변환 한 다음 원시 문자 ( chr(...))로 변환
  • [ x for y in z]- 목록 이해
  • ''.join(...) -문자 목록을 단일 문자열로 변환
  • print(...) -인쇄

1
참고 : |줄 끝의 많은 셸 에서 백 슬래시처럼 작동합니다. 명령은 다음 줄로 계속됩니다. 이런 식으로 백 슬래시를 거의 없앨 수 있습니다. LF 후 파이프 기호를 사용했는지 여부를 잘 모르겠습니다. 당신이 모르는 경우를 대비하여 다른 방법을 언급하고 있습니다.
Kamil Maciorowski 님이

1
몰랐어요, 고마워요! 나는 파이프 라인을 논리 라인으로 나누고 가시성 / 선명도 를 위해 파이프 |(또는 리디렉션 >, 부울 연산자 &&등)를 명시 적으로 명시 적으로 사용하는 것을 좋아 합니다. 아마도 스타일 / 환경 설정 일 것입니다.
Attie

1
몇 가지 생각 후에 나는 하나가 검사하여, 두 줄이 연결되어 말할 수 있기 때문에이 스타일을 사용하여 시작할 수 있는 중입니다. |끝에 있으면 다음 행이 독립형 명령처럼 보일 수 있으며 혼동 될 수 있습니다. 이것이 스타일이 당신의 정보에 근거한 결정이라고 생각하는 이유입니다.
Kamil Maciorowski

굉장, 어떻게되는지 알려주세요 :-)
Attie

1
그것은 무슨 . :)
Kamil Maciorowski

1

CodeGolf SE 사이트에 이것을 게시하려고 시도 할 수도 있지만 다음은 대체 파이썬 버전입니다 (킥 챌린지 용).

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 자로 서식이 지정 되었다고 가정 합니다.

이것은 Python 3 struct패키지와 stdin / out에 대한 쓰기 / 읽기를 사용합니다. (파이썬 2에서는 더 짧았을 것이다).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.