【问题标题】:Substitute pattern multiple times in same line在同一行中多次替换模式
【发布时间】:2012-09-22 19:39:46
【问题描述】:

我正在尝试使用正则表达式搜索/替换来用大括号(例如${foo})封装变量(例如$foo)。我想出了以下正则表达式,但它没有按预期工作:

s/"\([^"]*\)\$\([a-zA-Z0-9:]*\)\([^"]*\)"/"\1\${\2}\3"/g

但是,我对这种模式有一些问题。每个引用的字符串只会执行一种模式。这没关系,因为我可以在文件上多次运行表达式,但它不处理已经封装在大括号中的变量。它只是在它们上面放了第二组大括号。

我现在的想法是去掉 \2 的大括号,但我认为这不会起作用,因为模式仍然会匹配,并且每个引用的字符串只会执行 1 次替换。我查看了反向引用表达式文档,但无法确定更好的方法。

【问题讨论】:

    标签: regex sed preg-replace replace


    【解决方案1】:

    尝试以下方法:

    sed -e ':loop' -e 's/"\([^"]*\)\$\([a-zA-Z0-9:]\{1,\}\)\([^"]*\)"/"\1\${\2}\3"/' -e 't loop'
    

    这会将搜索/替换放入一个循环中,以便它会在每一行上重复尝试替换,直到无法进行更多替换为止。

    之所以有效,是因为当前正在处理的行仅在没有要运行的命令时打印,:loop 创建一个名为 loop 的标签,并且 t loop 仅在有是一个成功的替换。

    正如 potong 在 cmets 中所提到的,这可能会在带有多个引号的行上出现一些奇怪的行为,这是一种在这些情况下应该可以正常工作的替代方法:

    sed -e ':loop' -e 's/^\([^"]*\("[^"]*"[^"]*\)*\)"\([^"]*\)\$\([a-zA-Z0-9:]\{1,\}\)\([^"]*\)"/\1"\3\${\4}\5"/' -e 't loop'
    

    【讨论】:

    • 没问题,如果我的回答有效,您可以accept it,点击旁边的复选标记的轮廓。
    • 这只有在一行只有一对"'s 时才有效,即a "b" $c "d" 之类的数据最终会是a "b" ${c} "d"
    【解决方案2】:

    这可能对你有用(GNU sed):

    echo 'a "$a" b $b "b $b b $b" $c c $c "$c c $c"' | 
    sed 's/"\([^"]*\)"/"\n\1\n"/g;:a;s/\n\n//;ta;s/\n\$\([a-zA-Z0-9:]\+\)/${\1\}\n/;ta;s/\n\(.\)/\1\n/;ta'
    a "${a}" b $b "b ${b} b ${b}" $c c $c "${c} c ${c}"
    

    【讨论】:

    • 很好地解决了多引号问题。
    猜你喜欢
    • 2011-09-27
    • 1970-01-01
    • 2022-10-02
    • 1970-01-01
    • 1970-01-01
    • 2019-07-18
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    相关资源
    最近更新 更多