Bash
在命令行上表示/引用 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)
我可以證明第二個範例的合理性:
\0
可能被解釋為 EOS,但範例 4 中也應該是這種情況。範例 3 強調 GNU Parallel 不\0
將其視為 EOS,而是將其傳遞給bash
.你能解釋一下發生了什麼嗎?尤其是案例 4 讓我很困惑。
更重要的是:
有沒有辦法
\0
在命令行上引用,以便例如echo
看到它?
執行命令時,參數列表是傳遞給
execve()
系統呼叫的指向以 NUL 結尾的字元串的指針列表(就像傳遞給的另一個以 NUL 結尾的字元串列表的環境變數一樣execve()
)。因此,執行命令的參數和環境變數不能包含 NUL 字元。
例外是 shell 中的內置函式和函式,
zsh
其參數可以包含任何內容(這些是內置的,因此execve()
不涉及系統呼叫)。您可以通過標準輸入(或任何其他文件描述符)或任何類型的文件傳遞帶有 NUL 字元的數據。或者某些命令理解某種形式的編碼。
例如,符合 UNIX的
echo
實現\0
將(兩個字元反斜杠和零)理解為表示 NUL 字元。其他一些實現只有在傳遞-e
標誌時才會這樣做。所以:
echo '\0'
或者:
echo -e '\0'
可能導致
echo
輸出 NUL 字元後跟 LF 字元。與
zsh
,echo $'\0'
將 NUL 字元傳遞給
echo
內置函式。/bin/echo $'\0'
不起作用,因為
/bin/echo
is executed,所以它的參數不能包含 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$