【问题标题】:How do I correctly use captured groups from sed in my replacement text?如何在替换文本中正确使用 sed 中捕获的组?
【发布时间】:2015-02-03 05:22:48
【问题描述】:

只是没有足够的 sed 用户能够弄清楚这一点。我正在尝试将下划线转换为 lodash,这需要将许多调用从 _(obj).method() 更改为 _.method(obj)。我一直在尝试使用 sed 来做到这一点:

sed "s/_(\(.*\)).\(.*\)(/_.\2(\1, /"

这种模式实际上适用于一行中的单个实例。例如

echo "_(foo).bar('blah')" | sed "s/_(\(.*\)).\(.*\)(/_.\2(\1, /"

实际上输出了预期的结果:_.bar(foo, 'blah')。问题是当一行出现多次时。例如

echo "_(foo).bar('baz') yep _(baz).quux('blah')" | sed "s/_(\(.*\)).\(.*\)(/_.\2(\1, /"

输出_.quux(foo).bar('baz') yep _(baz, 'blah')

echo "_(foo).bar('baz') yep _(baz).quux('blah')" | sed "s/_(\([^(]*\)).\(.*\)(/_.\2(\1, /"

输出_.bar('baz') yep _(baz).quux(foo, 'blah')

所以,我显然只是不明白如何在我的替换文本中使用捕获组。顺便说一句,在末尾添加 /g 并不能解决此问题。

【问题讨论】:

    标签: sed


    【解决方案1】:

    这就是你要找的吗?

    sed -r 's/_\(([^)]*)\)\.([^(]*\()([^)]*\))/_.\2\1,\3/g'
    

    用你的例子:

    kent$  echo "_(foo).bar('baz') yep _(baz).quux('blah')" | sed -r 's/_\(([^)]*)\)\.([^(]*\()([^)]*\))/_.\2\1,\3/g'
    _.bar(foo,'baz') yep _.quux(baz,'blah')
    

    更新,您的代码上的 cmets:

    我查看了您的代码,并进行了一些修改,现在它可以在这里工作了。

    Yours : sed "s/_(\([^(]*\)).\(.*\)(/_.\2(\1, /"
    Mine  : sed "s/_(\([^)]*\))\.\([^(]*\)(/_.\2(\1, /g"
    
    • 记住,sed 总是贪婪匹配,所以,你必须使用[^something]。检查我改变的地方。
    • 当您希望点 (.) 与文字 . 匹配时,应将其转义。
    • 需要g 标志

    【讨论】:

    • 可能,尽管-r 在 Mac 上不存在。据说,相应的选项是-E,但是当我(以前)尝试过时,它说的是不匹配的括号。让我试试你的例子。
    • @tandrewnichols 我对 mac 的经验为零,但我猜你的意思是 bsd sed。我使用-r 因为,我们使用分组括号而不是文字括号,我只是想节省一些转义,您可以删除-r 并转义这些括号。
    • 是的,看起来它正在工作。愿意接受您的回答,尽管(无论如何对我来说)理解a)为什么我的不起作用,以及b)为什么您的回答会有所帮助。我喜欢学习。 :) 我会尝试阅读它,但是阅读 sed 正则表达式很困难......
    • @tandrewnichols:你的没用,因为.* 是贪婪的,跳过了源字符串中嵌入的)( 字符,而Kent 的代码没有这样做;它使用[^)]* 来避免吞噬) 字符。
    • @tandrewnichols 我刚刚更新了答案并添加了您的代码的修复程序。
    猜你喜欢
    • 1970-01-01
    • 2015-08-06
    • 2018-07-23
    • 2018-04-27
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 2019-10-16
    • 2023-03-07
    相关资源
    最近更新 更多