【问题标题】:Whether to escape ( and ) in regex using GNU sed是否使用 GNU sed 在正则表达式中转义 ( 和 )
【发布时间】:2011-09-17 06:58:54
【问题描述】:

我注意到该站点上的几篇帖子说,对于 gnu sed,您应该在正则表达式中使用 () 而不是 \(\)。但后来我查看了gnu sed manual,发现他们指定必须使用\(\)。怎么了?

【问题讨论】:

  • 您需要处理反斜杠。
  • 发生了一些事情,我无法分辨出您使用 ( 和 ) 的区别。至于我,我在使用正则表达式时总是逃避括号。
  • 你能链接到你提到的一些帖子吗?
  • 我总是在任何正则表达式中转义括号。如果手册上说要做,那就去做。
  • 我把`放在你的括号里,这样它们就会被当作代码处理

标签: regex bash sed gnu


【解决方案1】:

This part of the gnu sed manual you linked to 解释说是否应该转义括号取决于您使用的是基本正则表达式还是扩展正则表达式。 This part 表示 -r 标志决定了您处于哪种模式。

编辑:如 grok12 的评论中所述,bsd sed 中的 -E 标志与 gnu sed 中的 -r 标志的作用相同。

【讨论】:

  • 谢谢你,murgatroid。我现在意识到你的答案对于 gnu sed 是正确的,但对于 bsd sed 是不正确的,它使用 -E 标志来执行 -r 在 gnu sed 中所做的事情。
【解决方案2】:

最初的 sed,像 grep 和其他所有东西一样,使用 \( 来表示分组,而 ( 只是匹配一个文字的 open-paren。

许多较新的正则表达式实现,包括 egrep 和 perl,都改变了这一点,所以 \( 表示文字的开放括号,而 ( 用于指定分组。

所以现在使用 gnu sed,( 是一个特殊字符;就像 egrep 一样。但在其他系统(例如 BSD)上,据我所知,它仍然是旧方法。不幸的是,这真是一团糟,因为现在它很难知道该使用哪一个。

【讨论】:

  • 谢谢,克里斯。我现在意识到你的答案是正确的,除了 BSD sed 有一个 -E 选项来启用现代(扩展)正则表达式。
  • 关于“所以现在使用 gnu sed,( 是一个特殊字符;就像 egrep 一样” - 至少在我的 gnu sed 版本(Ubuntu 12.04,sed 版本)上似乎不是这样4.2.1). 默认仍然是"basic regexep" beaning () 是字面解释的。我需要-r 来启用扩展模式。
【解决方案3】:

感谢rocker、murga 和chris。你们每个人都帮助我理解了这个问题。我在这里回答我自己的问题是为了(希望)将整个故事放在一个地方。

目前使用的 sed 有两个主要版本:gnu 和 bsd。它们都要求基本正则表达式中的括号在用于分组时进行转义,但在用于扩展正则表达式时不进行转义。它们的区别在于 -r 选项为 gnu 启用扩展正则表达式,但 -E 为 bsd 启用。

mac OSX 中的标准 sed 是 bsd。我相信世界上很多其他地方都使用 gnu sed 作为标准,但我不确切知道谁使用了什么。如果您不确定您使用的是哪个,请尝试:

> sed -r

如果你得到一个

> sed: illegal option -- r

reply 那么你就有了bsd。

【讨论】:

  • 所以在基本表达式中,我应该使用 \( 进行分组,而仅使用 ( 进行匹配?
  • @Samuel 肯定的。
【解决方案4】:

转义括号 (\() 使正则表达式搜索括号作为表达式的一部分。

未转义的括号 (() 使正则表达式将括号的内容组合在一起。

换句话说,如果您将它们转义,引擎会寻找它们,但如果您保持原样,它们会导致引擎将结果分组到变量中。

举例说明:

$myString = "junk(150)moar";

仅获取号码:
#^\w+\((\d+)\)\w+$#

$1150

这是一团糟,我知道,但它演示了分组括号和括号作为匹配表达式的部分的使用。

几年后更新:

作为用户@bmk correctly points out,此答案适用于扩展正则表达式,但不适用于基本正则表达式。在大多数编程语言等中很难找到基本的正则表达式作为默认解析引擎,但在假设此答案适用于您的情况之前验证您使用的引擎是谨慎的。

【讨论】:

  • 在了解更多之后,我现在意识到您的回答对于基本正则表达式是正确的,但对于扩展正则表达式则不正确。
  • @grok12:实际上答案对于扩展的正则表达式是正确的,但对于基本的则不是......
  • 基本正则表达式是否相反?即使用 \( 进行分组和 ( 进行匹配?
  • @Samuel 我实际上并不了解正则表达式引擎的来龙去脉,但我的假设是基本的正则表达式很可能不执行分组。基本的正则表达式引擎通常是一种“单向”算法。换句话说,一旦一个字符通过了,它就会被遗忘。这将阻止分组工作,因为引擎需要收集它已经传递的内容,以防它需要将其收集到反向引用中。换句话说:不,相反的情况并非如此,实际上基本引擎中没有逆向,因为它们的操作方式不同。
猜你喜欢
  • 1970-01-01
  • 2021-01-04
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多