Shell

如何在 FreeBSD 的文件中插入 ESC 控製字元?

  • May 27, 2021

我想用兩個轉義命令(ESC+E 和 ESC+F)附上 Fortran 註釋。這意味著檢測以!直到行尾開頭的註釋,並在其前面ESC+E加上ESC+F.

第一次嘗試

$ echo "test line  ! Enclose this in ESC commands" | sed 's/\(!.*\)/\033E\1\033F/'
test line  033E! Enclose this in ESC commands033F

ESC 字元本身沒有生成,而是得到 033。

第二次嘗試

$ echo "test line  ! Enclose this in ESC commands" | sed $'s/\(!.*\)/\033E\1\033F/'
sh: Syntax error: Bad escape sequence

系統詳情

作業系統:FreeBSD 12。

外殼:sh.

賽德:sed

失敗的嘗試

這裡有兩個層次需要理解。首先,shell 處理輸入,然後將其傳遞給 Sed。

sed ’s/(!.*)/\033E\1\033F/'


單引號保留了裡面所有字元的字面意思,所以在第一次嘗試中,Sed 獲取了引號之間的所有字元。


但是,它失敗了,因為 Sed 不理解`\033`為 ASCII 八進制 033 (ESC)。您可能已經假設了,但[Sed 手冊](https://www.freebsd.org/cgi/man.cgi?query=sed&sektion=&n=1)對此隻字未提。
* ```
sed $'s/\(!.*\)/\033E\1\033F/'

構造$'...'是 ANSI C 引用。這是一個好主意,因為外殼隨後會轉換$'\033'為 ESC 字元。但是,FreeBSD 的 Sh 手冊 包含一個有效的反斜杠序列列表,然後清楚地說

任何其他以反斜杠開頭的字元串都是錯誤的。

它列出\(\)?不,因此錯誤消息。並且\1,應該去 Sed,也將被解釋為 ASCII 八進制 001 (SOH),這絕對不是你想要的。

解決方案

請注意,對於下面的選項 1 和 2,\033也可以簡單地寫為\e

  1. 只有 ANSI 引用\033轉義序列,其餘部分保留在正常引用中:
sed 's/\(!.*\)/'$'\033''E\1'$'\033''F/'
   ^^^^^^^^^^^^       ^^^^^       ^^^^
               ^^^^^^^     ^^^^^^^
  1. 不需要擷取組來擷取整個匹配的字元串。這是&預設的。
sed $'s/!.*/\033E&\033F/'
  1. (POSIX 兼容)使用 Printf 生成 ESC。選擇其中之一
esc=$(printf '\033'); sed "s/!.*/${esc}E&${esc}F/"
sed "s/!.*/$(printf '\033')E&$(printf '\033')F/"
  1. (符合 POSIX 標準)Awk。
awk '{sub(/!.*/, "\033E&\033F"); print}'

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