【问题标题】:Bash shell(grep) equivalent of this python regular expression?这个 python 正则表达式的 Bash shell(grep) 等价物?
【发布时间】:2026-01-10 10:50:01
【问题描述】:

我写了一个正则表达式来匹配python中的连字符

regexp = r"[a-z]+(?:-[a-z]+)*"

它匹配带有零个或多个连字符的单词。例如abc、acd-def、x-y-y 等。 但是,我找不到这个分组运算符 ?: 用于 shell(例如与 grep 一起使用)。在我看来,这只是 python 正则表达式的一个特性,而不是标准正则表达式。

谁能告诉我如何在 shell 中编写相同的正则表达式?

【问题讨论】:

  • 这是一个标准的non-capturing group。如果不能在 bash 中使用,请使用捕获组:[a-z]+(-[a-z]+)*
  • 删除非捕获组或为 grep 使用 -P 标志。 grep -Po "[a-z]+(?:-[a-z]+)*" file
  • 我认为这是How to use non-capturing groups in grep?的副本,但有一点疑问......

标签: regex bash


【解决方案1】:

(?:pattern) 匹配 pattern 而不捕获匹配的内容。它与以下* 一起使用,以允许您在不创建捕获组的情况下指定( ) 内容的零个或多个匹配项。如果您使用re.search() 之类的东西,这会影响python 中的结果,因为MatchObject 不会包含(?: ) 中的部分。在 grep 中,结果不是以相同的方式返回,因此只需删除 ?: 即可使用普通组:

grep -E '[a-z]+(-[a-z]+)*' file

这里我使用-E 开关来启用扩展的正则表达式支持。这将输出与模式匹配的每一行 - 您可以添加 -o 开关以仅打印匹配的部分。

正如 cmets 中提到的(谢谢),可以在 grep 中使用反向引用(如 \1)来引用模式内的先前捕获组,因此从技术上讲,行为是通过删除?: 进行了轻微更改,尽管这不是您目前正在做的事情,所以这并不重要。

【讨论】:

  • 啊,是的,在模式本身我猜是这样。好点,将编辑。
  • 您能解释一下您的第二点吗,因为您所指的评论已被删除?
【解决方案2】:

您的正则表达式不“匹配带连字符的单词” - 它匹配由[-a-z] 组成的单词,其中第一个和最后一个字符必须在[a-z] 中。 IE。它匹配[a-z](单字母单词)或[a-z][-a-z]*[a-z]

您的问题含糊不清 - bash 通常处理 通配符表达式grep 可以处理正则表达式

  • 重击

    这不能用通配符来完成。您可以在[[ ]] 括号内使用=~ 运算符:[[ $string =~ [a-z]|[a-z][-a-z]*[a-z] ]]

  • Grep

    您可以将两个正则表达式与| 结合起来,如下所示:[a-z]|[a-z][-a-z]*[a-z]

在问题的字里行间阅读 - “匹配连字符的单词”听起来更像是您想要一个像 [a-z]+(-[a-z]+)+ 这样的正则表达式,以便您的匹配中至少有一个 -

【讨论】: