繁体   English   中英

如何找到给定字符串中最后一次出现的子字符串?

[英]How to find last occurrence of a substring in a given string?

我有一个字符串,它描述了一些单词,如果结尾 == “jk”,我必须将它的结尾更改为“sd”。 例如,我有一个词:“lazer jk ”,我需要从中获取“lazer sd ”。

我尝试使用 method.gsub,。 但是如果我们在一个单词中多次出现子字符串“jk”,它就不能正常工作。

String#rindex返回给定子字符串最后一次出现的索引

String#[]=可以接受两个整数参数,第一个是开始替换的索引,第二个是被替换字符串的长度

您可以这样使用它们:

replaced = "foo"
replacing = "booo"

string = "foo bar foo baz"
string[string.rindex(replaced), replaced.size] = replacing

string
# => "foo bar booo baz"
"jughjkjkjk\njk".sub(/jk$\z/, 'sd')
 => "jughjkjkjk\nsd"

没有 $ 可能就足够了。

听起来您只想替换特定的后缀。 如果是这样,我可能会建议将sub与锚定的正则表达式一起使用(仅在字符串末尾检查所需的字符):

string_1 = "lazerjk"
string_2 = "lazerjk\njk"
string_3 = "lazerjkr"

string_1.sub(/jk\z/, "sd")  
#=>  "lazersd"

string_2.sub(/jk\z/, "sd")  
#=>  "lazerjk\nsd"

string_3.sub(/jk\z/, "sd")
#=>  "lazerjkr"

或者,您可以完全不使用正则表达式,而是使用reverse! 方法连同一个简单的条件语句来sub! 仅当存在后缀时:

string = "lazerjk"
old_suffix = "jk"
new_suffix = "sd"
string.reverse!.sub!(old_suffix.reverse, new_suffix.reverse).reverse! if string.end_with? (old_suffix)
string 
#=>  "lazersd"

或者,您甚至可以使用完全不同的方法。 这是一个使用chomp删除不需要的后缀然后将所需后缀ljust到修改后的字符串的示例。

string = "lazerjk"
string.chomp("jk").ljust(string.length, "sd")
#=>  "lazersd"

请注意,仅当使用初始 chomp 修改了字符串的长度时,才会添加新的后缀。 否则,字符串保持不变。

如果目标是替换 LAST OCCURRENCE(而不是仅后缀),那么这可以通过使用subreverse来完成:

string = "jklazerjkm"
old_substring = "jk"
new_substring = "sd"
string.reverse.sub(old_substring.reverse, new_substring.reverse).reverse
#=>  "jklazersdm"

用其他内容替换字符串末尾的"jk"很简单,无需担心字符串中可能存在的"jk"的其他实例即可解决,因此我认为这不是要求的内容。 相反,我假设问题是用"sd"替换字符串中"jk"的最后一个实例。

下面是两个将String#sub与正则表达式结合使用的解决方案。

使用否定的前瞻

这里的想法是匹配"jk" ,前提是它后面没有跟在字符串中的另一个实例"jk"

"lajkz\nejkrjklm".sub(/jk(?!.*jk)/m, "sd")
  #=> "lajkz\nejkrsdlm"

捕获字符串中最后一个"jk"之前的部分

匹配项(如果有的话)由字符串的前面和最后一个 "jk" 组成,最后一个"jk"被捕获的字符串替换,然后是"sd"

"lajkz\nejkrjklm".sub(/\A(.*)jk/m) { $1 + "sd" }
  #=> "lajkz\nejkrsdlm"

这两个正则表达式可以以自由间距模式编写,使它们成为自文档。 首先是以下内容。

/
jk    # match literal
(?!   # begin a negative lookahead
  .*  # match zero or more characters other than line terminators
  jk  # match literal
)     # end negative lookahead
/mx   # invoke multiline and free-spacing regex definition modes.

多行模式导致. 匹配任何字符,包括行终止符。

第二个正则表达式可以写成如下。

\A    # match the beginning of the string
(.*)  # match zero or more characters other than line terminators
      # and save the match to capture group 1
jk    # match literal
/mx   # invoke multiline and free-spacing regex definition modes.

请注意,在这两个表达式中.*都是贪心的,这意味着它会匹配尽可能多的字符,包括"jk" ,只要满足表达式的其他要求,此处匹配字符串中"jk"的最后一个实例.

这是一个不同的解决方案:

str = "jughjkjkjk\njk"
pattern = "jk"
replace_with = "sd"
str = str.reverse.sub(pattern.reverse, replace_with.reverse).reverse

暂无
暂无

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

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