可以\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)
我可以證明第二個例子是合理的:可能被解釋為EOS \0
,但是範例 4 中的情況也應該如此。\0
bash
你能解釋一下發生了什麼嗎——尤其是案例 4 讓我困惑。
更重要的是:
有沒有辦法\0
在命令列上引用以便egecho
看到它?
答案1
執行命令時,參數列表是傳遞給execve()
系統呼叫的指向 NUL 終止字串的指標列表(就像環境變量,它是傳遞給 的另一個 NUL 終止字串列表execve()
)。
結果,參數和環境變量被處決命令不能包含 NUL 字元。
例外情況是 shell 中的內建函數和函數,zsh
其參數可以包含任何內容(它們是內建的,因此execve()
不涉及系統呼叫)。
您可以透過 stdin(或任何其他檔案描述符)或在任何類型的檔案中傳遞帶有 NUL 字元的資料。或某些命令理解某種形式的編碼。
例如,符合 UNIX 規範的echo
實作將(兩個字元反斜線和零)理解\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 字元。其他一些 shell 的行為有所不同。
$ 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$