GNU 或 BSD Sed 中的正则表达式交替/或运算符 (foo|bar)

Gre*_*hal 44 shell sed regular-expression

我似乎无法让它发挥作用。GNU sed 文档说要转义管道,但这不起作用,也不能使用没有转义的直管。添加括号没有区别。

$ echo 'cat
dog
pear
banana
cat
dog' | sed 's/cat|dog/Bear/g'
cat
dog
pear
banana
cat
dog

$ echo 'cat
dog
pear
banana
cat
dog' | sed 's/cat\|dog/Bear/g'
cat
dog
pear
banana
cat
dog
Run Code Online (Sandbox Code Playgroud)

Mic*_*mer 57

默认情况下sed使用POSIX 基本正则表达式,其中不包括|交替运算符。您可以将其切换为使用Extended Regular Expressions,其中确实包括|交替-E(或-r在某些实现的某些旧版本中)。您可以使用:

echo 'cat dog pear banana cat dog' | sed -E -e 's/cat|dog/Bear/g'
Run Code Online (Sandbox Code Playgroud)

它将在兼容的系统上工作。(-e可选地标记 sed 脚本本身 - 您可以省略它,它只是防止某些类型的错误)

可移植到非常旧的seds 很复杂,但如果需要,您也可以切换到awk它,它在任何地方都使用 ERE。


Nid*_*dal 12

发生这种情况是因为它(a|b)是一个扩展的正则表达式,而不是一个基本的正则表达式。使用-E选项来处理这个问题。

echo 'cat
dog
pear
banana
cat
dog'|sed -E 's/cat|dog/Bear/g'
Run Code Online (Sandbox Code Playgroud)

sed手册页:

 -E      Interpret regular expressions as extended (modern) regular
         expressions rather than basic regular expressions (BRE's).
Run Code Online (Sandbox Code Playgroud)

请注意,这-r是同一件事的另一个标志,但-E更具可移植性,甚至会出现在下一版本的 POSIX 规范中。


mik*_*erv 10

执行此操作的可移植方式 - 也是更有效的方式 - 是使用地址。你可以这样做:

printf %s\\n cat dog pear banana cat dog |
sed -e '/cat/!{/dog/!b' -e '};cBear'
Run Code Online (Sandbox Code Playgroud)

这样,如果该行不包含字符串cat并且不包含字符串dog sed b ranches 退出脚本,则自动打印其当前行并拉入下一行以开始下一个循环。因此它不会执行下一条指令——在这个例子中,它c挂起整行来读取Bear,但它可以做任何事情。

可能还值得注意的是!b,该sed命令中的后面的任何语句只能匹配包含字符串dog或的行cat- 因此您可以执行进一步的测试而不会匹配不匹配的行 - 这意味着您现在可以应用规则只有一个或另一个。

但那是接下来。以下是上述命令的输出:

###OUTPUT###
Bear
Bear
pear
banana
Bear
Bear
Run Code Online (Sandbox Code Playgroud)

您还可以使用反向引用可移植地实现查找表。

printf %s\\n cat dog pear banana cat dog |
sed '1{x;s/^/ cat dog /;x
};G;s/^\(.*\)\n.* \1 .*/Bear/;P;d'
Run Code Online (Sandbox Code Playgroud)

为这个简单的示例案例进行设置需要做更多的工作,但从sed长远来看,它可以使脚本更加灵活。

在第一行中,我x更改了保持空间和模式空间,然后在将它们改回之前将字符串<space>cat <space>dog<space>插入保持空间x

从那时起,在接下来的每一行中,我都会G将空格附加到模式空间,然后检查从行首到我刚刚在末尾添加的换行符之间的所有字符是否与后面由空格包围的字符串匹配。如果是这样,我用Bear替换整个批次,如果不是,则不会造成任何伤害,因为我接下来P只打印模式空间中第一个出现的换行符,然后将d其全部删除。

###OUTPUT###
Bear
Bear
pear
banana
Bear
Bear
Run Code Online (Sandbox Code Playgroud)

当我说灵活时,我是认真的。这是更换BrownBearBlackBear

printf %s\\n cat dog pear banana cat dog |
sed '1{x;s/^/ 1cat Brown 2dog Black /;x
};G;s/^\(.*\)\n.* [0-9]\1 \([^ ]*\) .*/\2Bear/;P;d'

###OUTPUT###
BrownBear
BlackBear
pear
banana
BrownBear
BlackBear
Run Code Online (Sandbox Code Playgroud)

当然,您可以对查找表的内容进行大量扩展——我从Greg Ubben关于这个主题usenet 电子邮件中获得了这个想法,当时他在 90 年代描述了他如何用一个sed s///语句构建一个粗略的计算器。

  • 唷,+1。我必须说,你有跳出框框思考的倾向 (2认同)
  • @1_CR - 请参阅我的最后编辑 - 不是我的想法 - 这并不是说我不欣赏这一点并认为这是一种恭维。但我喜欢给予应得的信任。 (2认同)