Shell
如何在 FreeBSD 的文件中插入 ESC 控製字元?
我想用兩個轉義命令(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
。
- 只有 ANSI 引用
\033
轉義序列,其餘部分保留在正常引用中:sed 's/\(!.*\)/'$'\033''E\1'$'\033''F/' ^^^^^^^^^^^^ ^^^^^ ^^^^ ^^^^^^^ ^^^^^^^
- 不需要擷取組來擷取整個匹配的字元串。這是
&
預設的。sed $'s/!.*/\033E&\033F/'
- (POSIX 兼容)使用 Printf 生成 ESC。選擇其中之一
esc=$(printf '\033'); sed "s/!.*/${esc}E&${esc}F/" sed "s/!.*/$(printf '\033')E&$(printf '\033')F/"
- (符合 POSIX 標準)Awk。
awk '{sub(/!.*/, "\033E&\033F"); print}'