【问题标题】:Replace all strings in file, using wildcards in the substitution替换文件中的所有字符串,在替换中使用通配符
【发布时间】:2017-01-10 10:03:27
【问题描述】:

我在 bash 中使用 sed 来尝试替换所有匹配的字符串:

compile 'com.test.*:*'

与:

compile 'com.test.*:+'

其中 * 是通配符。

我的文件是这样的,叫做 moo.txt:

compile 'com.test.common:4.0.1'
compile 'com.test.streaming:5.0.10'
compile 'com.test.ui:1.0.7'

我希望它看起来像这样:

compile 'com.test.common:+'
compile 'com.test.streaming:+'
compile 'com.test.ui:+'

我尝试过像这样使用 sed:

sed -i -- "s/compile \'com.test.*:.*\'/compile \'com.test.*:+\'/g" moo.txt

但这会使文件看起来像:

compile 'com.test.*:+'
compile 'com.test.*:+'
compile 'com.test.*:+'

知道如何在替代字段中正确使用通配符吗?

【问题讨论】:

  • 查找捕获组。

标签: regex bash sed


【解决方案1】:
$ sed -E "s/[^:]+$/+'/" moo.txt 
compile 'com.test.common:+'
compile 'com.test.streaming:+'
compile 'com.test.ui:+'
  • [^:]+$ 匹配除: 之外的所有字符
  • 如果允许十六进制转义,请使用 sed -E 's/[^:]+$/+\x27/' 以避免在使用双引号时出现 shell 解释的可能性

要限定只有行的开头有compile 'com.test

sed -E "/^compile 'com.test/ s/[^:]+$/+'/" moo.txt

【讨论】:

    【解决方案2】:

    您正在匹配com.test 之后的内容,但您没有正确打印回来。

    所以你确实匹配了一些东西,只是你没有把它打印回来。相反,您正在打印文字 .*:

    sed "s/compile \'com.test.*:.*\'/compile \'com.test.*:+\'/g"
    #                        ^^                        ^^
    #                match this                  print back? NO
    

    为此,请捕获模式并使用反向引用将其打印回来。

    sed -E "s/compile 'com.test(.*):.*'/compile 'com.test\1:+'/g"
    #                          ^^^^                      ^^
    #                    catch this             print back! now YES!
    

    看到我们重复“编译...”太多了吗?这意味着我们可以将捕获扩展到行的开头,因为反向引用会将所有内容打印回来:

    sed -E "s/^(compile 'com.test.*):.*'/\1:+'/g"
    #          ^^^^^^^^^^^^^^^^^^^^^     ^^
    #           capture all of this      print it back
    

    注意-E 的用法允许sed 仅使用(...) 捕获组。如果我们不使用-E,我们应该使用\(...\)

    还请注意,您正在转义单引号,但没有必要,因为您在双引号内。

    【讨论】:

    • 太棒了,谢谢,这有效。是否可以添加许多反向引用,从而为您提供 \1 和 \2 等?
    • @user2010496 当然!您最多可以使用 9 个。检查例如 echo "hello how are" | sed -r 's/^([^ ]*) ([^ ]*) ([^ ]*)/\3 _ \2 _ \1/'
    • 这太美了!
    • 如果您使用-E 而不是-r,它将适用于BSD sed 以及较新版本的GNU sed。 -r 仅适用于 GNU sed,对于参数名称来说只是一个坏主意(如何在各种工具中启用 ERE?您使用 GNU grep -E、BSD sed -E 和 GNU sed -r?来吧... )。
    • @EdMorton 较新版本的 BSD sed 支持这两个标志,但 the -E flag will be standardized
    猜你喜欢
    • 2016-09-26
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 2016-10-08
    • 2011-10-11
    • 2017-05-27
    • 2022-11-19
    相关资源
    最近更新 更多