我想替换ruby中最后一个子字符串。什么是最简单的方式? 例如,在 abc123abc123 中,我想将最后的 abc 替换为 ABC 。我怎么能这样做?
答案 0 :(得分:35)
怎么样
new_str = old_str.reverse.sub(pattern.reverse, replacement.reverse).reverse
例如:
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"
答案 1 :(得分:21)
"abc123abc123".gsub(/(.*(abc.*)*)(abc)(.*)/, '\1ABC\4')
#=> "abc123ABC123"
但可能还有更好的方法......
编辑:
......克里斯在下面的评论中提供了。
因此,由于*
是一个贪婪的运算符,以下就足够了:
"abc123abc123".gsub(/(.*)(abc)(.*)/, '\1ABC\3')
#=> "abc123ABC123"
EDIT2:
还有一个解决方案巧妙地说明了Ruby中的并行数组赋值:
*a, b = "abc123abc123".split('abc', -1)
a.join('abc')+'ABC'+b
#=> "abc123ABC123"
答案 2 :(得分:6)
在大量数据流中搜索时,使用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"
相同的代码必须使用不出现sub_or_pattern
的字符串:
string = "hello_hello_hello"
# ...
# "hello_hello_hello"
* rpartition
在内部使用rb_str_subseq()
。我没有检查该函数是否返回该字符串的副本,但我认为它保留了该字符串部分使用的内存块。 reverse
使用rb_enc_cr_str_copy_for_substr()
,这表示副本一直在进行 - 尽管将来可能会实现更智能的String
类(将标记reversed
设置为是的,并且当它被设置时,它的所有函数都向后运行),到目前为止,效率很低。
此外,Regex
模式不能简单地逆转。这个问题只是要求替换最后一个子字符串,所以,这没关系,但是需要更强大的东西的读者不会从最多投票的答案中受益(截至撰写本文时)
答案 3 :(得分:5)
这是另一种可能的解决方案:
>> s = "abc123abc123"
=> "abc123abc123"
>> s[s.rindex('abc')...(s.rindex('abc') + 'abc'.length)] = "ABC"
=> "ABC"
>> s
=> "abc123ABC123"
答案 4 :(得分:2)
s = "abc123abc123abc"
p = "123"
s.slice!(s.rindex(p), p.size)
s == "abc123abcabc"
答案 5 :(得分:2)
您可以使用gsub和贪婪的regexp array(2) {
[0] => array(2) {
["caption"] => "c one"
["photos"] => "photo one"
}
[1] => array(2) {
["caption"] => "c two"
["photos"] => "photo two"
}
}
来实现这一目标:
.*
答案 6 :(得分:1)
string = "abc123abc123"
pattern = /abc/
replacement = "ABC"
matches = string.scan(pattern).length
index = 0
string.gsub(pattern) do |match|
index += 1
index == matches ? replacement : match
end
#=> abc123ABC123
答案 7 :(得分:1)
我已经使用了这个方便的辅助方法:
unique
如果你想让它更多Rails-y,请在String类本身上扩展它:
import numpy as np
a = np.array([1,2,2,3,4,2,4])
np.unique(a)
array([1, 2, 3, 4])
然后你可以直接在任何String实例上调用它,例如def gsub_last(str, source, target)
return str unless str.include?(source)
top, middle, bottom = str.rpartition(source)
"#{top}#{target}#{bottom}"
end
答案 8 :(得分:-1)
.gsub /abc(?=[^abc]*$)/, 'ABC'
匹配" abc"然后断言((?=)是正向前瞻),直到字符串末尾的其他字符都不是" abc"。