我想在(gollum)wiki页面中为关键短语添加markdown,该页面将链接到表单中的相关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
但是,如果同一行上的同一个关键短语有两个匹配项,则会遇到问题。因为我在线上插入东西,所以我在第一个匹配后找到的位置不准确。我知道我每次都可以根据插入的大小进行调整,但是因为我的插入对于每种光泽都有不同的大小,所以它似乎是最强力,最笨拙的解决方案。
是否有解决方案允许我同时在同一行上进行多次插入,而不是每次都进行多次任意调整?
答案 0 :(得分:2)
在看了@ BryceDrew的在线python版本之后,我意识到ruby可能也有办法填补这场比赛。我现在有一个更简洁,更快速的解决方案。
首先,我需要制作我的光泽的正则表达式:
glosses.push(/(?<![\[\(])#{gloss}(?![\]\)])/i)
注意:大多数正则表达式都是前瞻和后面的断言,以防止捕获已经是链接的短语。
然后,我需要制作所有这些union:
re = Regexp.union(glosses)
之后,就像在每一行上执行gsub一样简单,并填写我的匹配项:
File.foreach(target_file) do |line|
line = line.gsub(re) {|match| "[[#{match}|Glossary##{match.downcase}]]"}
puts line
end