Ruby 在同一行上查找和编辑多个正则表达式匹配项

Ruby 在同一行上查找和编辑多个正则表达式匹配项,ruby,regex,gollum-wiki,Ruby,Regex,Gollum Wiki,我想在(gollum)wiki页面中添加关键短语的标记,该页面将链接到以下表单中的相关wiki页面: This is the key phrase. 变成 This is the [[key phrase|Glossary#key phrase]]. 我有一个关键短语列表,例如: keywords = ["golden retriever", "pomeranian", "cat"] 和一份文件: Sue has 1 golden retriever. John has two cats.

我想在(gollum)wiki页面中添加关键短语的标记,该页面将链接到以下表单中的相关wiki页面:

This is the key phrase.
变成

This is the [[key phrase|Glossary#key phrase]].
我有一个关键短语列表,例如:

keywords = ["golden retriever", "pomeranian", "cat"]
和一份文件:

Sue has 1 golden retriever. John has two cats.
Jennifer has one pomeranian. Joe has three pomeranians.
我想迭代每一行,找到每个关键字的每个匹配项(还不是链接)。我当前的尝试如下所示:

File.foreach(target_file) do |line|
    glosses.each do |gloss|
        len = gloss.length
        # Create the regex. Avoid anything that starts with [
        # or (, ends with ] or ), and ignore case.
        re = /(?<![\[\(])#{gloss}(?![\]\)])/i
        # Find every instance of this gloss on this line.
        positions = line.enum_for(:scan, re).map {Regexp.last_match.begin(0) }
        positions.each do |pos|
            line.insert(pos, "[[")
            # +2 because we just inserted 2 ahead.
            line.insert(pos+len+2, "|#{page}\##{gloss}]]")
        end
    end
    puts line
end
File.foreach(目标文件)do |行|
上光。每个都上光|
len=光泽度。长度
#创建正则表达式。避免任何以[
#或(,以]或结尾),忽略大小写。
re=/(?)?
但是,如果同一行上有两个相同关键字短语的匹配项,则会出现问题。因为我在该行中插入了内容,所以在第一个匹配项之后,我发现每个匹配项的位置都不准确。我知道我每次都可以调整插入项的大小,但是,因为每个光泽的插入项大小不同,因此似乎是最残忍、最骇人的解决方案


有没有一种解决方案可以让我在同一行上同时进行多次插入,而每次都不需要进行几次任意调整?

在查看了@brycedew的在线python版本后,我意识到ruby可能也有一种方法来填补这一空缺。我现在有了一个更简洁、更快的解决方案

首先,我需要为我的手套制作正则表达式:

glosses.push(/(?<![\[\(])#{gloss}(?![\]\)])/i)
之后,只需在每一行上填写匹配项即可:

File.foreach(target_file) do |line|
  line = line.gsub(re) {|match| "[[#{match}|Glossary##{match.downcase}]]"}
  puts line
end

在看了@brycedew的在线python版本后,我意识到ruby可能也有一种方法来填补这一空缺。我现在有了一个更简洁、更快的解决方案

首先,我需要为我的手套制作正则表达式:

glosses.push(/(?<![\[\(])#{gloss}(?![\]\)])/i)
之后,只需在每一行上填写匹配项即可:

File.foreach(target_file) do |line|
  line = line.gsub(re) {|match| "[[#{match}|Glossary##{match.downcase}]]"}
  puts line
end

比如?@brycedruw感谢您的回复。这似乎基本上是正确的,但它不会对断言进行任何前瞻或后置操作,这将防止出现错误。理想情况下,我的脚本将在手动更新文档后在文档上运行,以添加新链接(而不会与现有链接发生冲突)@brycedew我找到了我的答案,主要是基于你的例子。非常感谢!比如?@brycedew感谢你的回答。这似乎基本上是正确的,但它不会做任何前瞻或后面的断言,这将阻止。理想情况下,我的脚本将在手动更新后在文档上运行,以添加新链接(不要弄乱现有的)。@brycedruve我找到了我的答案,主要是基于你的例子。非常感谢!你可能想在正则表达式的两边加上一个单词边界,以避免捕捉到例如“catapult”代表“cat”。类似这样的内容:
re=/\b{Regexp.union(glosss)}\b/
@Jordan我考虑过这个问题,但我确实希望捕捉复数和动词结尾,因此这是误报和误报之间的一种权衡。您可能希望在正则表达式的两侧设置一个单词边界,以避免捕捉例如“catapult”表示的“cat”。类似这样的内容:
re=/\b#{Regexp.union(glosss)}\b/
@Jordan我已经考虑过这个问题,但我确实想抓住复数和动词结尾,所以这是一个误报和误报之间的交易。