RegEx 替换适用于 Ruby gsub,但不适用于 sed

Posted

技术标签:

【中文标题】RegEx 替换适用于 Ruby gsub,但不适用于 sed【英文标题】:RegEx substitution works in Ruby gsub, but not with sed 【发布时间】:2016-02-28 21:48:31 【问题描述】:

我正在尝试从 SemVer 中去除前缀​​,即将 1.2.3-prefix.42 变成 1.2.3

我正在使用https://github.com/mojombo/semver/issues/32#issuecomment-7663411 中的这个正则表达式:

^(\d+\.\d+\.\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?

当使用 Ruby 的 gsub 方法时,它可以工作:

puts '1.2.3-alpha.4'.gsub(/^(\d+\.\d+\.\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/, '\1')
# => 1.2.3

但是当在终端使用sed 时,它不会:

$ echo '1.2.3-alpha.4' | sed -e 's/^(\d+\.\d+\.\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/\1/g'
$ 1.2.3-alpha.4

我错过了什么?

我在 Mac OS X 上使用 zsh。

谢谢

【问题讨论】:

我相信非捕获组 ((?: ... )) 在 sed 中不可用。更多信息:***.com/questions/4823864/… 虽然捕获组可能是您的主要问题,但如果 OSX 中 sed 的库存安装支持 \d,我会感到惊讶,请改用 [0-9]。祝你好运。 【参考方案1】:

如果你想让1.2.3-prefix.42这样的字符串变成1.2.3,你不必准备这么复杂的sed表达式。

只需检查字符串是否以由点分隔的三个数字的组合开头并捕获它。然后,打印回来:

$ sed -r 's/^([0-9]\.[0-9]\.[0-9]).*/\1/' <<< "1.2.3-prefix.42"
1.2.3

由于您在 Ruby 表达式中使用的其他模式使用 ?,我们可以假设它们是可选的,所以我不包括它们。

【讨论】:

谢谢@fedorqui,虽然你的答案是正确的,但你的答案在 OS X 的股票sed 上不起作用。 @mokagio 这很奇怪!我这里没有这样的版本,您可能需要添加输出以查看缺少的内容以使其与 BSD 兼容。【参考方案2】:

听起来你更喜欢使用 ruby​​,你可以像 sed 一样使用它:

echo '1.2.3-prefix.42' | ruby.exe -ne 'puts $_.sub /[^\d.].+/, ""'
#=> 1.2.3

如果你不需要,我认为你不会真的想学习 sed。

【讨论】:

谢谢@pguardiario。毕竟“解决问题的最简单方法就是一开始就没有它。”

以上是关于RegEx 替换适用于 Ruby gsub,但不适用于 sed的主要内容,如果未能解决你的问题,请参考以下文章

RegEx 不适用于 .NET,但适用于其他 RegEx 实现

正则表达式适用于 regex101.com,但不适用于 prod

正则表达式适用于 regex101.com,但不适用于 prod

我的正则表达式适用于 regex101 但不适用于 python? [复制]

Ruby gsub 替换值的单反斜杠?

Ruby 匹配第一次出现的字符串以进行 gsub 替换