简体   繁体   English

在同一行中多次替换模式

[英]Substitute pattern multiple times in same line

I'm trying to come up with a regex search/replace to encapsulate variables (eg; $foo ) with braces (eg; ${foo} ). 我正在尝试用正则表达式搜索/替换来封装变量(例如; $foo )和大括号(例如; ${foo} )。 I came up with the following regex, but it's not working as intended: 我提出了以下正则表达式,但它没有按预期工作:

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

However, I have some problems with this pattern. 但是,我对这种模式有一些问题。 It will only do one pattern per quoted string. 每个引用的字符串只会执行一个模式。 This is OK, since I can run the expression multiple times on the file but it doesn't handle variables already encapsulated in braces. 这没关系,因为我可以在文件上多次运行表达式,但它不处理已经封装在大括号中的变量。 It just puts a second set of braces on them. 它只是在它们上面放了第二组括号。

My idea now is to strip \\2 of braces, but I don't think this will work since the pattern will still match and it will only perform 1 substitution per quoted string. 我现在的想法是剥离\\2个大括号,但我认为这不会起作用,因为模式仍然匹配,并且它只会对每个引用的字符串执行1次替换。 I looked at backreference expression documentation but I'm not able to determine a better approach. 我查看了反向引用表达文档,但我无法确定更好的方法。

Try the following: 请尝试以下方法:

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

This puts the search/replace into a loop so that it will repeatedly attempt the replacement on each line until no more replacements can be done. 这会将搜索/替换放入循环中,以便它会在每行上重复尝试替换,直到不再需要替换为止。

This works because the current line being processed is only printed when there are no more commands to be run, :loop creates a label named loop , and t loop returns execution to the label loop only if there was a successful substitution. 这是有效的,因为正在处理的当前行仅在没有更多命令要运行时打印, :loop创建一个名为loop的标签,并且只有在成功替换时, t loop loop才会将执行返回到标签loop

As mentioned by potong in comments, this can have some strange behavior on lines with multiple quotes, here is an alternative that should work properly in these scenarios: 正如potong在评论中所提到的,这可能在具有多个引号的行上有一些奇怪的行为,这里有一个在这些场景中应该正常工作的替代方法:

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

This might work for you (GNU sed): 这可能适合你(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}"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM