2016-04-22 8 views
2

Ich versuche ein Programm zu schreiben, das Bibelverse innerhalb eines Dokuments mit jeder gewünschten Übersetzung ersetzen kann. Dies ist nützlich für ältere Bücher, die viele KJV-Verse enthalten. Der schwierigste Teil des Prozesses besteht darin, die Verse in einem Dokument zu extrahieren.C# regulärer Ausdruck zum Finden eines bestimmten Musters in einem Text

Ich finde, dass die meisten Bücher, die Bibelverse im Text platzieren, eine Struktur wie "N"(BookName chapter#:verse#s) verwenden, wobei N der Verstext ist, die Zitate sind wörtlich und die Parens sind auch wörtlich. Ich habe Probleme mit einem regulären Ausdruck, um diese in einem Text zu finden.

Der letzte reguläre Ausdruck, den ich versuche zu verwenden, ist dies: \"(.+)\"\s*\(([\w. ]+[0-9\s]+[:][\s0-9\-]+.*)\). Ich habe Probleme, wo es nicht alle Spiele finden wird.

Hier ist die Regex101 davon mit einem Beispiel. https://regex101.com/r/eS5oT8/1

Gibt es trotzdem eine Lösung mit einem regulären Ausdruck? Jede Hilfe oder Vorschläge würde sehr geschätzt werden.

+1

Sie haben vergessen, die globale Flagge, Stock ein 'g' in der Box auf der rechten Seite in Ihrem regex101 Beispiel. Wenn dies nicht mit .Matches in C# funktioniert, zeigen Sie uns diesen Code. –

+0

Verwenden Sie den Modifikator "g", damit es beim ersten Spiel nicht aufhört –

+0

Verwenden Sie den g-Schalter, um alle zu vergleichen. –

Antwort

1

Es ist erwähnenswert, dass die Site, die Sie zum Testen verwendeten, auf Javascript Reguläre Ausdrücke angewiesen ist, die den Modifikator g explizit definieren müssen, im Gegensatz zu C# (das standardmäßig global ist).

Sie können Ihren Ausdruck leicht anpassen und sicherstellen, dass Sie richtig Ihre doppelten Anführungszeichen zu entkommen:

// Updated expression with escaped double-quotes and other minor changes 
var regex = new Regex(@"\""([^""]+)\""\s*\(([\w. ]+[\d\s]+[:][\s\d\-]+[^)]*)\)"); 

Und dann die Regex.Matches() Methode verwenden, alle Spiele in der Zeichenfolge zu finden:

// Find each of the matches and output them 
foreach(Match m in regex.Matches(input)) 
{ 
    // Output each match here (using Console Example) 
    Console.WriteLine(m.Value); 
} 

Sie können es in Aktion in this working example mit Beispielausgabe sehen, die unten gesehen wird:

enter image description here

+0

Ich denke, ich kann ein neues Problem gefunden haben. Was machst du für Verse, die eine Reihe von Zitaten enthalten? Es gibt viele Verse, die das haben, und mit dieser Reg-Exp scheint es zu brechen. Zum Beispiel: "Dies ist eine neue Botschaft," geh und hab Spaß. "Die Leute waren erstaunt." (Buch 3: 2). Mit dem aktuellen reg exp wird es von "gehen und Spaß haben ..., aber ich möchte, dass es die ganze Sache erfasst". Dies ist eine neue Nachricht, denn das wäre der ganze Vers, wenn es ein Zitat enthält innerhalb. – ktconrad90

+0

Sie könnten den Ausdruck explizit sagen, dass Sie wissen, dass er endet, wenn ein ')' erreicht ist. Wenn Sie also Ihren Ausdruck leicht in '@" ändern würden ([^ \)] +) \ "" \ s * \ (([\ w.] + [0-9 \ s] + [:] [\ s0-9 \ -] + [^)] *) \ "", sollte es Ihr Problem lösen, wie [hier] (https://dotnetfiddle.net/CTiLSa) gesehen –

+0

Dies funktioniert für Anführungszeichen. Aber es gibt auch einige Verse mit Parens darin. Das bricht auch das Spiel. Gibt es dafür eine andere Lösung? – ktconrad90

1

Verwenden Sie den Modifizierer "g".

g Modifizierer: global. Alle Spiele (nicht zurück auf erste Spiel)

das Sehen Regex Demo

0

Sie mit Beispiel gegeben versuchen können hier in MSDN ist der Link

https://msdn.microsoft.com/en-us/library/0z2heewz(v=vs.110).aspx

using System; mit System.Text.RegularExpressions;

public class Example 
{ 
    public static void Main() 
    { 
     string input = "ablaze beagle choral dozen elementary fanatic " + 
        "glaze hunger inept jazz kitchen lemon minus " + 
        "night optical pizza quiz restoration stamina " + 
        "train unrest vertical whiz xray yellow zealous"; 
     string pattern = @"\b\w*z+\w*\b"; 
     Match m = Regex.Match(input, pattern); 
     while (m.Success) { 
     Console.WriteLine("'{0}' found at position {1}", m.Value, m.Index); 
     m = m.NextMatch(); 
     } 
    } 
} 
// The example displays the following output: 
// 'ablaze' found at position 0 
// 'dozen' found at position 21 
// 'glaze' found at position 46 
// 'jazz' found at position 65 
// 'pizza' found at position 104 
// 'quiz' found at position 110 
// 'whiz' found at position 157 
// 'zealous' found at position 174 
0

Nachdem Sie „g“ hinzugefügt haben, auch vorsichtig sein, wenn es mehrere Verse ohne '\n' Charakter dazwischen sind, weil "(.*)" sie als ein langes Spiel behandeln wird anstelle von mehreren Versen. Sie wollen etwas wie "([^"]*)", um das zu verhindern.

1

Wie wäre es als Leitfaden mit dieser Start:

(?<quote>"".+"")   # a series of any characters in quotes 
\s +      # followed by spaces 
\(      # followed by a parenthetical expression 
    (?<book>\d*[a-z.\s] *) # book name (a-z, . or space) optionally preceded by digits. e.g. '1 Cor.' 
    (?<chapter>\d+)  # chapter e.g. the '1' in 1:2 
    :      # semicolon 
    (?<verse>\d+)   # verse e.g. the '2' in 1:2 
\)    

die Optionen:

RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.IgnoreCase 

Der obige Ausdruck wird von Ihnen genannten Aufnahmen von jedem Element in dem Spiel für die einfache Analyse geben (zB , können Sie Zitat, Buch, Kapitel und Vers auswählen, indem Sie zum Beispiel auf match.Groups["verse"] schauen.

Voll Code:

var input = @"Jesus said, ""'Love your neighbor as yourself.' 
      There is no commandment greater than these"" (Mark 12:31)."; 

var bibleQuotesRegex = 
    @"(?<quote>"".+"")    # a series of any characters in quotes 
    \s +       # followed by spaces 
    \(        # followed by a parenthetical expression 
      (?<book>\d*[a-z.\s] *) # book name (a-z, . or space) optionally preceded by digits. e.g. '1 Cor.' 
      (?<chapter>\d+)   # chapter e.g. the '1' in 1:2 
      :      # semicolon 
      (?<verse>\d+)   # verse e.g. the '2' in 1:2 
    \)"; 
foreach(Match match in Regex.Matches(input, bibleQuotesRegex, RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.IgnoreCase)) 
{ 
    var bibleQuote = new 
    { 
     Quote = match.Groups["quote"].Value, 
     Book = match.Groups["book"].Value, 
     Chapter = int.Parse(match.Groups["chapter"].Value), 
     Verse = int.Parse(match.Groups["verse"].Value) 
    }; 

    //do something with it. 
}