\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
구현은 (2개의 문자, 백슬래시 및 0)을 \0
NUL 문자로 해석합니다. 일부 다른 구현에서는 -e
플래그가 전달될 때만 이 작업을 수행합니다.
그래서:
echo '\0'
또는:
echo -e '\0'
echo
NUL 문자 뒤에 LF 문자가 출력될 수 있습니다.
그리고 zsh
,
echo $'\0'
echo
내장 문자 에 NUL 문자를 전달합니다 .
/bin/echo $'\0'
/bin/echo
그대로 작동하지 않습니다처형된이므로 해당 매개변수에는 NUL 문자가 포함될 수 없습니다.
네 번째 질문에 관해서. 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$