Ruby仅替换作为哈希传递的多个正则表达式的第一次出现

时间:2018-05-23 16:07:25

标签: ruby regex gsub

我有一段文字,并希望只有Ruby sub这个词的第一个正则表达式匹配。如果我只需要匹配一个字符串,那就没问题了,但是我将多个正则表达式传递给了我的子字符串:

regex = Regexp.new(["Lebron James", "Chris Paul"].join("|"))
names_hash = {"Lebron James" => "**Lebron James**", "Chris Paul" => "**Chris Paul**"}

str = "of the best players left in the playoffs, Lebron James is the most experienced player left in the field and probably in all of the league. Chris Paul has played in many playoff games but has never been to a conference final. Lebron James on the other hand, has been to seven straight NBA finals."

如果我运行str.gsub(regex, names_hash),Lebron James和Chris Paul的所有实例都会被替换为:

  

“季后赛中最好的球员,勒布朗詹姆斯是最多的   经验丰富的球员留在场上,可能在所有的球员   联盟。 克里斯·保罗曾参加太多季后赛,但从未参加过   去过一次会议决赛。 Lebron James 另一方面,已经   连续七次进入NBA总决赛。“

如果我运行str.sub(regex, names_hash)(sub而不是gsub),我只会第一次出现Lebron James,而不是Chris Paul:

  

“季后赛中最好的球员,勒布朗詹姆斯是最多的   经验丰富的球员留在场上,可能在所有的球员   联盟。克里斯保罗参加了很多季后赛,但从未参加过比赛   参加决赛。另一方面,勒布朗詹姆斯已经去过   连续七次进入NBA总决赛。“

我的问题:

我如何设置我拥有的东西,以便我可以取代勒布朗詹姆斯和克里斯保罗的第一个例子,但不是勒布朗詹姆斯的第二个参考?我的预期结果:

  

“季后赛中最好的球员,勒布朗詹姆斯是最多的   经验丰富的球员留在场上,可能在所有的球员   联盟。 克里斯·保罗参加了很多季后赛,但从未参加过   参加决赛。另一方面,勒布朗詹姆斯已经去过   连续七次进入NBA总决赛。“

2 个答案:

答案 0 :(得分:4)

怎么样:

regex = Regexp.new(["Lebron James", "Chris Paul"].join("|"))
names_hash = {"Lebron James" => "**Lebron James**", "Chris Paul" => "**Chris Paul**"}
str = "of the best players left in the playoffs, Lebron James is the most experienced player left in the field and probably in all of the league. Chris Paul has played in many playoff games but has never been to a conference final. Lebron James on the other hand, has been to seven straight NBA finals."


str.gsub(regex) { |name| names_hash.delete(name) || name }

仅在第一次替换时从names_hash读取;之后,gsub将"默认"不做任何改动。

请注意,此方法会改变原始names_hash - 因此如果以后需要变量,您可能需要事先dup

答案 1 :(得分:1)

虽然Tom Lords answer很好,但我想向您展示一种解决问题的不同方法。我的解决方案涉及调用String#sub和你名字一样多次。

str = 'of the best players left in the playoffs, Lebron James is the most experienced player left in the field and probably in all of the league. Chris Paul has played in many playoff games but has never been to a conference final. Lebron James on the other hand, has been to seven straight NBA finals.'
names = ['Lebron James', 'Chris Paul']

原始回答

replacements = names.map { |name| "**#{name}**" }
replacements = names.zip(replacements)

replacements.inject(str) { |str, args| str.sub(*args) }

作为mudasobwa pointed out in the comments #map / #zip 可能有点矫枉过正。你可以改为运行以下代码:

names.inject(str) { |str, name| str.sub(name, "**#{name}**") }

<强>返回

  

&#34;在季后赛中留下的最佳球员中,勒布朗詹姆斯是场上最有经验的球员,并且可能在整个联盟中。 克里斯·保罗曾参加多场季后赛,但从未参加过会议决赛。另一方面,勒布朗詹姆斯已经连续七次进入NBA总决赛。&#34;

<强>引用

相关问题