\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)
2番目の例を正当化できます。\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$