在命令列中表示/引用 NUL

在命令列中表示/引用 NUL

可以\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 中的情況也應該如此。\0bash

你能解釋一下發生了什麼嗎——尤其是案例 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$

相關內容