如何使用 Bash / ZSH 在字元串中正確生成 ascii 字元?
我正在嘗試生成一個字元串,
10
後跟一個NULL
(\0
),然後是一個10
.但是
echo "10\010"
似乎不起作用(我猜它會生成兩個字元 - a10
後跟\010
。我不確定如何分隔/轉義這些值/字元?我也試過
echo "10""/0""10"
了,結果是一樣的。我將此輸出通過管道傳輸到命名管道。
在符合 POSIX 的外殼中,您可以使用:
echo '10\000010'
請注意,
echo
需要三個八進制數字跟隨 a\0
來終止八進制轉義序列。您的問題是
bash
在這種情況下不符合 POSIX,因為它沒有實現XSI
非嵌入式 UNIX 變體所需的支持。
bash
但是部分支持printf
,因此您可以使用:printf '10\00010\n'
更好地使用 printf為什麼 printf 比 echo 更好?因為許多的原因:
$ printf '%b' 10 \\0 10 1010
或
printf '%b' 10 '\0' 10
(並使用 od 查看字節值(或sed l
或cat -A
):$ printf '%b' 10 '\0' 10 | od -An -c 1 0 \0 1 0
請注意,按照您的要求,該字元串沒有尾隨
\n
(換行符)。如果需要換行符,請使用:
$ printf '%b' 10 \\0 10 '\n' | sed l 10\00010$
我不確定如何分隔/轉義這些值/字元?
分隔字元的唯一安全方法是將它們放在單獨的參數中。
但是使用
echo
起來很複雜並且容易失敗,因為有多個版本的 echo。在 bash (問題中的標籤)中, echo 需要
-e
選擇使其理解反斜杠值的選項(並使用 od (或sed l
orcat -A
)查看字節值:$ echo -e 10 '\0' 10 | od -An -c 1 0 \0 1 0 \n
這適用於 bash、zsh、ksh 和(GNU)
/bin/echo
(至少)。但是 echo 包含一個需要刪除的空格字元(ASCII 字元 32 dec(20 十六進制 40 八進制))。
$ echo -e 10 '\0' 10 | tr -d ' ' | od -An -c 1 0 \0 1 0 \n
而且,該
-e
選項不會被 echo 的某些實現(如破折號)解釋:$ dash -c 'echo -e 10 \\0 10' -e 10 10
甚至反斜杠也不會被某些迴聲解釋:
$ echo -e 10 '\0' 10 -e 10 \0 10
即使POSIX 規範將反斜杠八進制數定義為最多三位(以零開頭):
\0num
寫入一個 8 位值,它是零、一、二或三位八進制數 num。
$ zsh -c 'echo -e h \\00044 h | od -An -tx1c' 68 20 04 34 20 68 0a h 004 4 h \n
也接受較少的數字:
$ zsh -c 'echo -e h \\4 h | od -An -tx1c' 68 20 04 20 68 0a h 004 h \n
那是一種解釋,而且像往常一樣,任何解釋都是誤解的根源。
所以,簡而言之,避免 echo 並使用 printf。
即使 printf 也可以解釋最多四個八進制數字(使用
\b
選項),如果每個值都是單獨的參數,則不會有任何誤解:$ printf '%b' 10 '\55' 10 '\n' 10-10