【问题标题】:Why does sed match something outside the group as part of the group?为什么 sed 将组外的东西匹配为组的一部分?
【发布时间】:2017-02-09 03:48:03
【问题描述】:

我最近尝试使用 sed 从逗号和换行符分隔的枚举成员中生成一堆方法。我遇到了以下看起来不直观的行为:

$ echo 'Hello,' | sed 's/\(.*\),\?/"Hi \1!"/g'
"Hi Hello,!"

在这里,我尝试通过\(.*\) 将逗号之前的所有内容捕获到一个组中,然后我允许使用,\? 使用可选的逗号。我希望这会将\1 替换为第一个逗号之前的所有内容,即Hello,但由于某种原因,逗号也被包含在替换中,尽管它不在组内。为什么会这样?

【问题讨论】:

    标签: linux bash unix sed terminal


    【解决方案1】:

    正则表达式默认进行贪婪匹配(从左到右),如果最贪婪的匹配不起作用,则回溯。所以在\(.*\),\? 的情况下,最贪婪的匹配是将Hello, 匹配到\(.*\) 而没有匹配到,\?

    我不确定如何在基本正则表达式中进行非贪婪匹配(这是sed 使用的)。在 Perl 样式的正则表达式(sed 不使用)中,您在匹配运算符后放置一个问号,因此您可以使用类似 (.*?),? 的内容。

    您可以做的下一个最好的事情是使用\([^,]*\),\? 之类的东西,但它会在它看到的第一个逗号处停止匹配。

    【讨论】:

      【解决方案2】:

      这是因为 sed 正则表达式是贪婪的,而 ? 量词意味着匹配前面标记的 0 或 1 -- 在本例中为 ,

      所以,这里的引擎贪婪地匹配到最后,并且由于?? 设为可选,它也被包含在捕获的组(.*) 中。

      要获得所需的行为,请删除?

      %  echo 'Hello,' | sed 's/\(.*\),\?/"Hi \1!"/g'
      "Hi Hello,!"
      
      %  echo 'Hello,' | sed 's/\(.*\),/"Hi \1!"/g' 
      "Hi Hello!"
      

      【讨论】:

      • 感谢您的回复。最后的逗号必须是可选的,因为我正在尝试匹配枚举成员,而最后一个没有逗号。
      猜你喜欢
      • 2011-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-24
      • 2022-01-18
      • 2022-01-01
      相关资源
      最近更新 更多