Bash

如何使用 Bash / ZSH 在字元串中正確生成 ascii 字元?

  • August 29, 2018

我正在嘗試生成一個字元串,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 lcat -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 lor cat -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

引用自:https://unix.stackexchange.com/questions/465262