如何在 FreeBSD 中的文件中插入 ESC 控制字符?

如何在 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

答案1

失败的尝试

这里有两个层次需要理解。首先 shell 处理输入,然后将其传递给 Sed。

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

    单引号保留内部所有字符的字面含义,因此在第一次尝试中,Sed 获取引号之间的所有字符。

    但是,它失败了,因为 Sed 不理解\033ASCII 八进制 033 (ESC)。您可能已经假设了这一点,但是sed手册对此什么也没说。

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

    $'...'构造是 ANSI C 引用。这是一个好主意,因为 shell 随后会转换$'\033'为 ESC 字符。然而,FreeBSD 的 Sh 手册 包含有效反斜杠序列的列表,然后清楚地说

    任何其他以反斜杠开头的字符串都是错误的。

    是否列出\(\)?不,因此出现错误消息。并且\1,应该发送到 Sed,也会被解释为 ASCII 八进制 001 (SOH),这绝对不是您想要的。

解决方案

请注意,对于下面的选项 1 和 2,\033也可以简单地写为\e

  1. 只有 ANSI 引用转义\033序列,将其余部分保留在正常引用中:

    sed 's/\(!.*\)/'$'\033''E\1'$'\033''F/'
        ^^^^^^^^^^^^       ^^^^^       ^^^^
                    ^^^^^^^     ^^^^^^^
    
  2. 不需要捕获组来捕获整个匹配的字符串。这是&默认的。

    sed $'s/!.*/\033E&\033F/'
    
  3. (符合 POSIX)使用 Printf 生成 ESC。选择其中一项

    esc=$(printf '\033'); sed "s/!.*/${esc}E&${esc}F/"
    sed "s/!.*/$(printf '\033')E&$(printf '\033')F/"
    
  4. (符合 POSIX 标准)awk。

    awk '{sub(/!.*/, "\033E&\033F"); print}'
    

相关内容