如何替换ruby中最后一个子串?

时间:2010-07-06 09:46:11

标签: ruby

我想替换ruby中最后一个子字符串。什么是最简单的方式? 例如,在 abc123abc123 中,我想将最后的 abc 替换为 ABC 。我怎么能这样做?

9 个答案:

答案 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"。