bash는 16 진수 값 0x00을 변수에 저장할 수 없습니다


11

dd로 몇 가지 트릭을 시도하고 있습니다. 16 진수 값을 "header"라는 변수에 저장하여 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

답변:


16

Bash는 C 스타일 문자열을 사용하기 때문에 문자열에 널 바이트를 저장할 수 없습니다.이 문자열은 종료자를 위해 널 바이트를 예약합니다. 따라서 Bash가 중간에 저장하지 않고 널 바이트를 포함하는 시퀀스를 파이프하기 위해 스크립트를 다시 작성해야합니다. 예를 들어 다음과 같이 할 수 있습니다.

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

그건 그렇고, 당신은 필요하지 않습니다 echo; Bash를 printf다른 많은 간단한 작업에 사용할 수 있습니다 .

또는 체인 대신 임시 파일을 사용할 수 있습니다.

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

물론 이것은 파일 /tmp/mysequence이 이미 존재할 수 있다는 문제가 있습니다. 이제 임시 파일을 작성하고 경로를 문자열로 저장해야합니다.

또는 프로세스 대체를 사용하여이를 피할 수 있습니다.

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

<(command)연산자의 출력을 수신 할 파일 시스템의 명명 된 파이프를 생성 command. hd첫 번째 인수로 파이프에 대한 경로를받습니다.이 파이프는 거의 모든 파일처럼 열고 읽을 수 있습니다. /unix//a/17117/136742 에서 자세한 내용을 확인할 수 있습니다 .


1
정확하지만 이것은 정확한 이유가 아니라 구현 세부 사항입니다. 나는 그것을 보았고 POSIX 표준 에는 실제로이 행동이 필요 하므로 실제 이유가 있습니다. (일부 지적했듯이, zsh그렇게 할 수는 있지만 논 POSIX 모드에서만 가능합니다.) 나는 이것을 구현할 가치가 있는지 궁금해하기 때문에 실제로 그것을 보았습니다 mksh...
— mirabilos

@mirabilos, 당신은 그것을 확장 하시겠습니까? AFAICT, 출력에 NUL 문자가있을 때 명령 대체에 대해 POSIX마다 동작이 지정되지 않으며 POSIX 모드의 zsh에 대해 유일하게 생각할 수있는 유일한 차이점은 sh에뮬레이션 \0에서 기본값이에 있지 않다는 것입니다 $IFS. 에뮬레이션에서 echo "$(printf 'a\0b')"여전히 작동합니다 . shzsh
— Stéphane Chazelas

3
@mirabilos 쉘이 POSIX 표준보다 10 년 이상 앞서 있다고 생각 하면 실제 실제 이유는 쉘이 C 스타일 문자열을 사용하고 표준이 그 주위에 구축되었다는 것을 알 수 있습니다.
— giusti

printf와 echo에 대한 자세한 논의를 위해 좋은 Q를 찾았습니다. unix.stackexchange.com/questions/65803/…
— Paulb

8

zsh변수에 NUL 문자를 저장할 수있는 유일한 쉘인 대신 사용할 수 있습니다 . 해당 문자는 기본값 $IFSin에 zsh있습니다.

nul=$'\0'

또는:

nul=$'\x0'

또는

nul=$'\u0000'

또는

nul=$(printf '\0')

그러나 인수 및 환경 변수가 시스템 호출에 전달되는 NUL 구분 문자열 (쉘이 아닌 시스템 API의 제한) 이므로 실행 되는 명령에 인수 또는 환경 변수와 같은 변수를 전달할 수 execve()없습니다. ). 에서가 zsh, 당신은 그러나 NUL 함수 또는 명령 내장 인수로 바이트를 전달할 수 있습니다.

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

1
"zsh를 대신 사용할 수 있습니다." 고마워요-저는 초보자로서 배쉬 스크립팅을 가르치고 있습니다. 다른 구문과 혼동하고 싶지 않습니다. 그러나 제안 해 주셔서 대단히 감사합니다
— Frank

실제로 zsh질문에 구문 을 사용 했습니다. echo -n $header콘텐츠의 전달을 의미하기 $header위해 마지막 인자로 변수 echo -n이다 zsh(또는 fish또는 rc또는 es) 구문 아닌 bash 구문. 에서 bash가, 매우 다른 의미를 . 더 일반적으로 zsh같다 ksh( bash는 GNU 쉘, 다소의 파트 복제되고 ksh, 유닉스 사실상 쉘에게)하지만 함께 Bourne 씨의 디자인 특질의 대부분이 고정 (기능과 특징을 많이하고, 많은 쉘을 더 사용자 친화적 / 덜 놀라운).
— Stéphane Chazelas

주의 : zsh는 때때로 0 바이트를 변경할 수 있습니다 echo $(printf 'ab\0cd') | od -vAn -tx1c .`61 62 20 63 64 0a`를 인쇄합니다. 즉, NUL이 있어야합니다.
— Isaac

1
그리고 그것은 다른 (없음, 없음) 쉘이 재현하지 않는 것입니다. 따라서 스크립트는 zsh에서 매우 특별한 방식으로 동작합니다. 내 의견으로는 : zsh는 너무 영리하려고합니다.
— Isaac

2
zsh 스크립트 작성에 익숙해 졌다는 POSIX sh 표준에있는 디자인의 잘못된 기능을 "수정"하면 다른 쉘에서 연습 할 경우 버그가있는 관행에 익숙해 짐을 의미합니다. 이것은 기술이나 습관이 전이되지 않는 다른 언어와 달리 구문과 관련하여 문제가되지는 않지만 실제로는 그렇지 않습니다.
— Charles Duffy 2012
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.