sed 音译中的转义字符

Jas*_*ann 7 freebsd sed string tr macos

我想使用sed的音译 ( y///) 将一组字符替换为另一组字符。

我希望这与使用该程序一样有效tr

$ echo '[]{}abc' | tr '[ab}' 'gefh' 
g]{hefc
Run Code Online (Sandbox Code Playgroud)

但是,当我使用 sed 执行相同的操作时,我看到以下错误:

$ echo '[]{}abc' | sed 'y/[ab}/gefh/' 
sed: 1: "y/[ab}/gefh/": unbalanced brackets ([])
Run Code Online (Sandbox Code Playgroud)

这是有道理的,因为我预计需要转义该[角色。但是,当我尝试逃避这种情况时,我收到以下不同的错误:

$ echo '[]{}abc' | sed 'y/\[ab}/gefh/' 
sed: 1: "y/\[ab}/gefh/": transform strings are not the same length
Run Code Online (Sandbox Code Playgroud)

我当前的解决方法是(1)仅使用tr或(2)在音译的右侧插入一个“虚拟字符”,其作用除了匹配转义字符之外什么也不做。

$ echo '[]{}abc' | sed 'y/\[ab}/_gefh/' 
g]{hefc
Run Code Online (Sandbox Code Playgroud)

然而,这并不令人满意且值得怀疑。它也不是很安全,例如当\位于输入字符串中时。

$ echo '[]{}abc\' | sed 'y/\[ab}/_gefh/' 
g]{hefc_
Run Code Online (Sandbox Code Playgroud)

在 sed 音译中转义字符而不将转义字符本身视为翻译的一部分的正确方法是什么?

Kus*_*nda 6

假设你使用的是 macOS(这是sed我可以在本机上显示此问题的唯一系统,尽管我还没有检查 macOS 的 FreeBSD 是从哪里来sed的):

$ echo '[]{}abc' | sed 'y/[ab}/gefh/'
sed: 1: "y/[ab}/gefh/": unbalanced brackets ([])
Run Code Online (Sandbox Code Playgroud)
$ echo '[]{}abc' | sed 'y/\[ab}/gefh/'
sed: 1: "y/\[ab}/gefh/": transform strings are not the same length
Run Code Online (Sandbox Code Playgroud)
$ echo '[]{}abc' | sed 'y/\[ab}/\gefh/'
g]{hefc
Run Code Online (Sandbox Code Playgroud)

所以,一种解决方案是

  1. 转义[第一个字符串中的 以避免括号不平衡,并且
  2. 通过向第二个字符串添加“无操作”反斜杠,使两个字符串的长度相等。

或者,

  • 您还可以将两个字符串都包含在 中[...],经过反思,这可能是处理此问题的最安全方法,因为它可以以机械方式完成,而无需关心字符串位于字符串中的位置[

    $ echo '[]{}abc' | sed 'y/[[ab}]/[gefh]/'
    g]{hefc
    
    Run Code Online (Sandbox Code Playgroud)
  • sed或者通过 macOS 上的 Homebrew 或 FreeBSD 的软件包系统安装 GNU ,并使用它。

我会将其视为此sed实现中的一个错误。

  • FreeBSD 11.2 也有同样的错误。BusyBox 1.30.1 有类似的错误。据猜测,他们重用了解析正则表达式中的字符集的代码,并且解析了字符类(例如“[:alnum:]”),即使它们不使用该解析的结果(正确的是:“y/ [:alnum:]/…/` 应该替换字符 `:almnu[]`,而不是字母数字字符)。 (3认同)