2016-06-30 9 views
0

I Abschlags auf die Schlüsselsätze in einer (Gollum) Wiki-Seite hinzufügen möchten, die auf die entsprechende Wiki-Seite in Form verbinden wird:Suchen und Bearbeiten mehrerer Regex Spiele auf der gleichen Linie

This is the key phrase. 

Wird

This is the [[key phrase|Glossary#key phrase]]. 

ich habe eine Liste der wichtigsten Sätze wie:

keywords = ["golden retriever", "pomeranian", "cat"] 

Und ein Dokument:

Sue has 1 golden retriever. John has two cats. 
Jennifer has one pomeranian. Joe has three pomeranians. 

Ich möchte über jede Zeile iterieren und finde jedes Match (das ist nicht schon ein Link) für jedes Keyword. Mein aktueller Versuch sieht wie folgt aus:

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 

Dies ist jedoch auf ein Problem stoßen, wenn es zwei Spiele für den gleichen Schlüssel Satz auf der gleichen Linie. Weil ich Dinge in die Linie einfüge, ist die Position, die ich für jedes Match gefunden habe, nach dem ersten nicht korrekt. Ich weiß, dass ich mich jedes Mal an die Größe meiner Einfügungen anpassen kann, aber da meine Einfügungen für jeden Glanz eine andere Größe haben, scheint es die brutalste, hacky Lösung zu sein.

Gibt es eine Lösung, die es mir ermöglicht, mehrere Einfügevorgänge gleichzeitig auf derselben Leitung ohne mehrere willkürliche Anpassungen vorzunehmen?

+1

Wie [dies] (https://regex101.com/r/qY5zV6/2)? –

+0

@BryceDrew Danke für die Antwort. Das scheint größtenteils richtig zu sein, aber es führt nicht zu voraus oder hinter Aussagen, die verhindern würden, [den Link zu bestehenden Links hinzuzufügen] (https://regex101.com/r/cU3qI1/3). Im Idealfall würde mein Skript nach der manuellen Aktualisierung auf einem Dokument ausgeführt werden, um neue Links hinzuzufügen (ohne bestehende zu stören). –

+0

@BryceDrew Ich habe meine Antwort weitgehend auf Ihr Beispiel gefunden. Danke vielmals! –

Antwort

2

Nachdem ich @ BryceDrew's Online-Python-Version angeschaut habe, habe ich gemerkt, dass Ruby wahrscheinlich auch eine Möglichkeit hat, das Match zu füllen. Ich habe jetzt eine viel präzisere und schnellere Lösung.

Zuerst musste ich Regexes meiner Glossen machen:

glosses.push(/(?<![\[\(])#{gloss}(?![\]\)])/i) 

Hinweis: Die Mehrheit dieser regex ist vorausschauende und Blick hinter Behauptungen eine Phrase zu verhindern fangen, die bereits Teil eines Links ist.

Dann habe ich ein union alle von ihnen machen benötigt:

re = Regexp.union(glosses) 

Danach ist es so einfach wie gsub auf jeder Linie zu tun, und das Ausfüllen meiner Begegnungen:

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

Wahrscheinlich möchten Sie auf beiden Seiten Ihres regulären Ausdrucks eine Wortgrenze setzen, um z. "Katapult" für "Katze" Etwa so: 're = /\b#{Regexp.union(glosses)} \ b /'. –

+0

@ Jordan Ich habe darüber nachgedacht, aber ich möchte Plural und Verb Ende zu fangen, so ist es ein Handel zwischen falsch negativen und falsch positiven. –

Verwandte Themen