\0
명령줄에서 사용할 수 있나요 ?
배경
GNU Parallel의 특수 사례를 테스트하기 위해 명령줄에서 모든 문자가 올바르게 인용되었는지 궁금했습니다. 대부분은 다음과 같습니다.
perl -e 'print pack ("c*",1..255,10)' | parallel -k echo | md5sum
d03484ca75b3e38be411198d66bf4611 -
perl -e 'print pack ("c*",1..255,10)' | md5sum
d03484ca75b3e38be411198d66bf4611 -
하지만 \0
까다로운 것 같습니다(여기서는 로 설명됨 A\0B\n
).
perl -e 'print pack ("c*",65,0,66,10)' | wc -c
4 (A\0B\n)
perl -e 'print pack ("c*",65,0,66,10)' | parallel echo | wc -c
2 (A\n)
perl -e 'print pack ("c*",65,0,66,10)' | parallel --dry-run echo | wc -c
9 (echo A\0B\n)
perl -e 'print "echo ",pack ("c*",65,0,66,10)' | bash | wc -c
3 (AB\n)
두 번째 예를 정당화할 수 있습니다. \0
EOS로 해석될 수 있지만 예 4에서도 마찬가지입니다. 예 3에서는 GNU Parallel이 \0
EOS로 간주 하지 않고 bash
.
무슨 일이 일어나고 있는지 설명해 주시겠습니까? 특히 사례 4가 저를 당황하게 합니다.
그리고 더 중요한 것은:
예 를 들어 볼 수 \0
있도록 명령줄에서 인용하는 방법이 있습니까 ?echo
답변1
명령을 실행할 때 인수 목록은 execve()
시스템 호출에 전달된 NUL 종료 문자열에 대한 포인터 목록입니다( 에 전달된 다른 NUL 종료 문자열 목록인 환경 변수와 유사 execve()
).
결과적으로, 인수와 환경 변수는처형된명령에는 NUL 문자가 포함될 수 없습니다.
인수에 무엇이든 포함될 수 있는 내장 및 함수는 예외입니다 zsh
(이것들은 내장되어 있으므로 execve()
시스템 호출이 관련되지 않습니다).
stdin(또는 다른 파일 설명자)을 통해 또는 모든 유형의 파일에서 NUL 문자가 포함된 데이터를 전달할 수 있습니다. 또는 일부 명령은 특정 형태의 인코딩을 이해합니다.
예를 들어, UNIX 규격 echo
구현에서는 \0
(두 문자 백슬래시와 0)을 NUL 문자를 의미하는 것으로 이해합니다. 일부 다른 구현에서는 -e
플래그가 전달된 경우에만 이를 수행합니다.
그래서:
echo '\0'
또는:
echo -e '\0'
echo
NUL 문자 다음에 LF 문자가 출력 될 수 있습니다 .
와 함께 zsh
,
echo $'\0'
NUL 문자를 echo
내장에 전달합니다.
/bin/echo $'\0'
작동하지 않을 것 /bin/echo
입니다.처형된이므로 해당 인수에는 NUL 문자가 포함될 수 없습니다.
포인트 4 질문에 관해서. bash는 해당 NUL 문자를 무시합니다. 일부 다른 쉘은 다르게 동작합니다.
$ printf 'e\0cho a\0b\n' | bash |& sed -n l
ab$
$ printf 'e\0cho a\0b\n' | ksh |& sed -n l
ksh: syntax error at line 1: `zero byte' unexpected$
$ printf 'e\0cho a\0b\n' | zsh |& sed -n l
zsh: command not found: e$
$ printf 'e\0cho a\0b\n' | rc |& sed -n l
line 1: warning: null character ignored$
line 1: warning: null character ignored$
ab$