我想替换ruby中最后一次出现的子串.什么是最简单的方式?例如,在abc123abc123中,我想将最后一个abc替换为ABC.我怎么能这样做?
Cho*_*ett 36
怎么样
new_str = old_str.reverse.sub(pattern.reverse, replacement.reverse).reverse
Run Code Online (Sandbox Code Playgroud)
例如:
irb(main):001:0> old_str = "abc123abc123"
=> "abc123abc123"
irb(main):002:0> pattern="abc"
=> "abc"
irb(main):003:0> replacement="ABC"
=> "ABC"
irb(main):004:0> new_str = old_str.reverse.sub(pattern.reverse, replacement.reverse).reverse
=> "abc123ABC123"
Run Code Online (Sandbox Code Playgroud)
Mla*_*vić 22
"abc123abc123".gsub(/(.*(abc.*)*)(abc)(.*)/, '\1ABC\4')
#=> "abc123ABC123"
Run Code Online (Sandbox Code Playgroud)
但可能还有更好的方法......
编辑:
......克里斯在下面的评论中提供了.
所以,就像*一个贪婪的运算符,以下就足够了:
"abc123abc123".gsub(/(.*)(abc)(.*)/, '\1ABC\3')
#=> "abc123ABC123"
Run Code Online (Sandbox Code Playgroud)
EDIT2:
还有一个解决方案巧妙地说明了Ruby中的并行数组赋值:
*a, b = "abc123abc123".split('abc', -1)
a.join('abc')+'ABC'+b
#=> "abc123ABC123"
Run Code Online (Sandbox Code Playgroud)
小智 12
从 Ruby 2.0 开始,我们可以使用\Kwhich 从返回的匹配中删除在它之前匹配的任何文本。结合贪婪的运算符,你会得到这个:
'abc123abc123'.sub(/.*\Kabc/, 'ABC')
#=> "abc123ABC123"
Run Code Online (Sandbox Code Playgroud)
这比 Hirurg103 建议的使用捕获组快大约 1.4 倍,但这种速度是以使用鲜为人知的模式降低可读性为代价的。
更多信息\K:https : //www.regular-expressions.info/keep.html
您可以使用String#sub和贪婪正则表达式来实现此目的.*,如下所示:
'abc123abc123'.sub(/(.*)abc/, '\1ABC')
Run Code Online (Sandbox Code Playgroud)
这是另一种可能的解决方案:
>> s = "abc123abc123"
=> "abc123abc123"
>> s[s.rindex('abc')...(s.rindex('abc') + 'abc'.length)] = "ABC"
=> "ABC"
>> s
=> "abc123ABC123"
Run Code Online (Sandbox Code Playgroud)
在大量数据流中搜索时,reverse明确使用会导致性能问题.我用string.rpartition*:
sub_or_pattern = "!"
replacement = "?"
string = "hello!hello!hello"
array_of_pieces = string.rpartition sub_or_pattern
( array_of_pieces[(array_of_pieces.find_index sub_or_pattern)] = replacement ) rescue nil
p array_of_pieces.join
# "hello!hello?hello"
Run Code Online (Sandbox Code Playgroud)
相同的代码必须使用不出现的字符串sub_or_pattern:
string = "hello_hello_hello"
# ...
# "hello_hello_hello"
Run Code Online (Sandbox Code Playgroud)
*内部rpartition 使用rb_str_subseq().我没有检查该函数是否返回该字符串的副本,但我认为它保留了该字符串部分使用的内存块.reverse使用rb_enc_cr_str_copy_for_substr(),这表明副本一直在进行- 尽管将来String可能会实现一个更智能的类(将标志reversed设置为true,并且在设置时使其所有功能都向后运行),截至目前,效率低下.
而且,Regex模式不能简单地逆转.这个问题只是要求替换子串的最后一次出现,所以,没关系,但是需要更强大的东西的读者不会从最投票的答案中受益(截至本文撰写时)
| 归档时间: |
|
| 查看次数: |
18880 次 |
| 最近记录: |