当前位置:  开发笔记 > 编程语言 > 正文

gsub部分替换

如何解决《gsub部分替换》经验,为你挑选了2个好方法。

我想在此表达式中仅替换括号中的组:

my_string.gsub(/<--MARKER_START-->(.)*<--MARKER_END-->/, 'replace_text')

这样我得到: <--MARKER_START-->replace_text<--MARKER_END-->

我知道我可以重复整个MARKER_STARTMARKER_END在替换表达式中阻塞,但我认为应该有一个更简单的方法来做到这一点.



1> Orion Edward..:

您可以使用零宽度前瞻和后置断言来完成此操作.

这个正则表达式应该在ruby 1.9和perl以及许多其他地方工作:

注意:ruby 1.8仅支持先行断言.你需要前瞻和后视来正确地做到这一点.

 s.gsub( /(?<=<--MARKER START-->).*?(?=<--MARKER END-->)/, 'replacement text' )

ruby 1.8中发生的事情是?<=它崩溃的原因,因为它不理解后面的断言.对于那部分,你必须回到使用反向引用 - 比如Greig Hewgill提到的

所以你得到的是

 s.gsub( /(<--MARKER START-->).*?(?=<--MARKER END-->)/, '\1replacement text' )

解释第一:

我用(.)*正则表达式中间替换了.*?- 这是非贪婪的.如果你没有非贪婪,那么你的正则表达式会尝试尽可能多地匹配 - 如果你在一行上有2个标记,就会出错.最好通过示例说明:

"One Two Three".gsub( /.*<\/b>/, 'BOLD' )
=> "BOLD"

我们真正想要的是:

"One Two Three".gsub( /.*?<\/b>/, 'BOLD' )
=> "BOLD Two BOLD"

解释第二:

零宽度前瞻声明听起来像一堆书呆子混乱.

什么"超前断言"实际上意味着"只有匹配,如果我们正在寻找的东西,其次是其他东西.

例如,只匹配一个数字,如果它后跟一个数字.

"123F" =~ /\d(?=F)/ # will match the 3, but not the 1 or the 2

"零宽度"实际上意味着"在我们的搜索中考虑'后跟',但在进行替换或分组或类似事情时不要将其视为匹配的一部分.使用相同的123F示例,如果我们没有不要使用先行断言,而只是这样做:

"123F" =~ /\dF/ # will match 3F, because F is considered part of the match

正如你所看到的,这是检查我们的理想选择<--MARKER END-->,但我们需要的<--MARKER START-->是能够说"只匹配,如果我们正在寻找的东西跟随其他东西".这被称为后视断言,红宝石1.8没有出于某种奇怪的原因.

希望有道理:-)

PS:为什么使用先行断言而不仅仅是反向引用?如果你使用前瞻,你实际上并没有替换<--MARKER-->位,只有内容.如果你使用反向引用,你将取代整个批次.我不知道这是否会引起很多性能损失,但从编程的角度来看,这似乎是正确的做法,因为我们实际上根本不想更换标记.



2> Greg Hewgill..:

你可以这样做:

my_string.gsub(/(<--MARKER_START-->)(.*)(<--MARKER_END-->)/, '\1replace_text\3')

推荐阅读
云聪京初瑞子_617
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有