셸 도구만 사용하여 NULL(0x00 문자)이 포함된 바이너리 스트림을 편집하고 출력 스트림에서 0x00 문자를 유지하려면 어떻게 해야 합니까?
편집하려면 아래와 같이 지정된 위치의 한 문자를 다른 문자(아래 예에서는 "|" 문자)로 바꿔야 합니다.
dd ibs=1 skip=$offset count=$reglen status=none if=$ARQ |
sed 's/./\|/2' |
sed 's/./\|/5' #| more replacements....
그러나 sed는 교체하기 전에 '\0x00' 문자를 모두 제거합니다.
편집 - @George Vasiliou의 테스트를 사용하여 내 환경에서 sed 동작을 보여줍니다.
$ echo -e "lineA\nlineB\nlineC" | tr '\n' '\0' | od -t x1
0000000 6c 69 6e 65 41 00 6c 69 6e 65 42 00 6c 69 6e 65
0000020 43 00
0000022
$ echo -e "lineA\nlineB\nlineC" | tr '\n' '\0' | sed 's/./|/5' | od -t x1
0000000 6c 69 6e 65 7c 6c 69 6e 65 42 6c 69 6e 65 43
0000017
내 환경은 AIX 7.1이고 sed에는 GNU 버전이 없습니다.
답변1
sed
는텍스트유용. 그것은 적용됩니다텍스트 라인(개행으로 구분된 NUL이 아닌 문자(바이트 아님)의 제한된 길이 시퀀스).
2 번째 와 5번째를 바꾸고 싶다면 바이트바이트 시퀀스이지만 여러 가지 이유로 작동하지 않습니다.
sed
텍스트에 적용됩니다. 입력에 NUL 문자가 포함되어 있고, 줄 바꿈으로 끝나지 않고, 두 줄 바꿈 사이에 LINE_MAX 바이트 이상이 있고, 유효한 문자를 형성하지 않는 바이트 시퀀스가 포함되어 있으면(구현에 따라)sed
전혀 작동하지 않습니다. (GNU에는sed
이러한 제한 사항이 많지 않습니다.)- 해당 이진 입력이 유효한 텍스트를 형성하더라도
.
바이트가 아닌 문자와 일치하므로 여러 바이트가 일치할 수 있습니다. - sed 코드는 각각에 대해 실행되기 때문에철사입력의 두 번째 및 다섯 번째 문자는 전체 입력의 두 번째 및 다섯 번째 문자가 아닌 각 줄의 두 번째 및 다섯 번째 문자를 변경합니다.
입력을 NUL 바이트 제한이나 길이 제한 없이 임의의 바이트 배열로 처리하려면 다음을 사용할 수 있습니다 perl
.
dd.... | perl -0777 -pe 'for $o (1, 4) {substr($_, $o, 1) = "|"}'
예:
$ printf 'a\0b\0cd' |
> perl -0777 -pe 'for $o (1, 4) {substr($_, $o, 1) = "|"}' |
> od -Ax -tx1 -tc
000000 61 7c 62 00 7c 64
a | b \0 | d
000006
vim
또는 도우미 를 사용하여 중간 텍스트 표현을 사용할 수 있습니다 xxd
.
dd... | xxd -p | sed '1s/../7c/2;1s/../7c/5' | xxd -p -r
xxd -p
기본적으로 16진수 덤프는 한 줄에 60자로 제공됩니다. 위에서 첫 번째 줄의 두 번째와 다섯 번째 2자리 16진수 숫자를 7c
ASCII 숫자로 대체했습니다 |
.
답변2
답변3
확실합니까? 간단한 테스트로 볼 때 제 경우에는 이런 일이 발생하지 않는 것 같습니다(gnu sed 4.2.2).
$ echo -e "lineA\nlineB\nlineC"
lineA
lineB
lineC
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0'
lineAlineBlineC
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/5'
line|lineBlineC
# Verification if the nulls are still there:
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/5' |tr '\0' '\n'
line|
lineB
lineC
추가 테스트 후 테스트에서 6번째 문자(빈 위치)를 바꾸면 null이 손실됩니다.
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/6' |tr '\0' '\n'
lineA|lineB
lineC
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/7' |tr '\0' '\n'
lineA
|ineB
lineC