2009-12-20 9 views
22

Ich bin auf der Suche nach einem guten regulären .NET-Ausdruck, den ich für die Analyse einzelner Sätze aus einem Textkörper verwenden kann.Was ist ein regulärer Ausdruck zum Analysieren einzelner Sätze?

Hello world! How are you? I am fine. 
This is a difficult sentence because I use I.D. 

Newlines should also be accepted. Numbers should not cause 
sentence breaks, like 1.23. 

ein wenig mehr Dies erweist sich schwieriger als ich ursprünglich gedacht:

Es sollte folgende Textblock in genau sechs Sätze analysieren können.

Jede Hilfe würde sehr geschätzt werden. Ich werde das verwenden, um das System auf bekannte Textstellen zu trainieren.

+0

@Luke: Es sah aus wie Sie einen sichtbaren Zeilenumbruch zwischen „Ursache“ und „Satz“ in dem Beispieltext wollten, aber es zeigte mich nicht. Ich zwang es zu zeigen, indem ich zwei Leerzeichen vor dem Zeilenvorschub einfügte. So wollten Sie es aussehen lassen, oder? –

+0

Ja, Sie sind genau richtig! Danke, dass du das getan hast. Dumm mich (immer noch ein Noob). –

Antwort

36

Versuchen Sie, diese @"(\S.+?[.!?])(?=\s+|$)":

string [email protected]"Hello world! How are you? I am fine. This is a difficult sentence because I use I.D. 
Newlines should also be accepted. Numbers should not cause sentence breaks, like 1.23."; 

Regex rx = new Regex(@"(\S.+?[.!?])(?=\s+|$)"); 
foreach (Match match in rx.Matches(str)) { 
    int i = match.Index; 
    Console.WriteLine(match.Value); 
} 

Ergebnisse:

Hello world! 
How are you? 
I am fine. 
This is a difficult sentence because I use I.D. 
Newlines should also be accepted. 
Numbers should not cause sentence breaks, like 1.23. 

Für komplizierte, natürlich, benötigen Sie einen echten Parser wie SharpNLP oder NLTK. Meine ist nur eine schnelle und dreckige. Hier

sind die SharpNLP Informationen und Funktionen:

SharpNLP ist eine Sammlung von natürlichen Sprachverarbeitung Tool geschrieben in C#. Derzeit bietet es die folgenden NLP-Werkzeuge:

  • ein Satz Teiler
  • ein tokenizer
  • ein Teil-of-Speech-Tagger
  • ein chunker (verwendet, um „nicht-rekursive syntaktische Annotationen zu finden wie Nominalphrase Chunks ")
  • ein Parser
  • ein Name Finder
  • ein Koreferenz Werkzeug
  • eine Schnittstelle zur lexikalischen Datenbank WordNet
+3

+1 für uns auf SharpNLP, die ich nicht zuvor gesehen hatte und kann sehr nützlich sein. –

+0

Verwenden Sie besser eine Look-Ahead-Assertion für '(?: \ S + | $)'. – Gumbo

+0

Danke für Info Gumbo, es ist besser, aber ich musste \ S in der Front hinzufügen, weil Whitespaces auf der linken Seite strippen müssen. – YOU

2

Dies ist nicht wirklich möglich, mit nur regulären Ausdrücke, wenn Sie nicht genau wissen, welche „schwierig“ Token Sie, wie „id“ haben, „Herr“ usw. Wie viele Sätze lautet beispielsweise "Bitte zeigen Sie Ihre ID, Mr. Bond."? Ich kenne keine C# -Implementierungen, aber ich habe NLTK Punkt tokenizer verwendet. Wahrscheinlich sollte es nicht zu schwer sein, es neu zu implementieren.

5
var str = @"Hello world! How are you? I am fine. This is a difficult sentence because I use I.D. 
Newlines should also be accepted. Numbers should not cause sentence breaks, like 1.23."; 

Regex.Split(str, @"(?<=[.?!])\s+").Dump(); 

Ich habe dies in LINQPad getestet.

+0

Danke, dass du es ausprobiert hast. –

5

Es ist nicht möglich, Regexes zu verwenden, um natürliche Sprache zu analysieren. Was ist das Ende eines Satzes? Eine Periode kann an vielen Stellen auftreten (z.B. z.B.). Sie sollten ein Parsing-Toolkit für natürliche Sprachen wie OpenNLP oder NLTK verwenden. Leider gibt es nur sehr wenige Angebote in C#. Möglicherweise müssen Sie daher einen Webservice erstellen oder sich anderweitig in C# einklinken.

Beachten Sie, dass es in der Zukunft Probleme verursachen wird, wenn Sie sich auf exakte Leerzeichen wie in "I.D." verlassen. Sie werden bald Beispiele finden, die Ihre Regex brechen. Zum Beispiel legen die meisten Leute Leerzeichen nach ihren Initialen.

Es gibt eine ausgezeichnete Zusammenfassung der offenen und kommerziellen Angebote in WP (http://en.wikipedia.org/wiki/Natural_language_processing_toolkits). Wir haben einige von ihnen benutzt. Es ist die Mühe wert.

[Sie verwenden das Wort "Zug". Dies ist normalerweise mit maschinellem Lernen verbunden (was ein Ansatz für NLP ist und zum Satzteilen verwendet wurde). In der Tat beinhalten die Toolkits, die ich erwähnt habe, maschinelles Lernen. Ich vermute, das war nicht das, was du meintest - eher, dass du deinen Ausdruck durch Heuristik weiterentwickeln würdest. Nicht]

+0

Danke für diese Info. Ich bin immer fasziniert von dem Aspekt des maschinellen Lernens und das ist ein Aspekt, den ich gerne untersuchen würde. Für meinen jetzigen Zweck glaube ich, dass der einfache Regex-Ansatz (bei dem ich nicht von diesen seltsamen Fällen, von denen du sprichst, erwartet wird) in Ordnung ist. Ich werde jedoch versuchen, die Frameworks, von denen Sie sprechen, weil sie bereits existieren. –

0

habe ich die Vorschläge hier gepostet und kam mit dem regex bis die Nähte zu erreichen, was ich tun möchte:

(?<Sentence>\S.+?(?<Terminator>[.!?]|\Z))(?=\s+|\Z) 

I Expresso verwendet, um mit:

// using System.Text.RegularExpressions; 
/// <summary> 
/// Regular expression built for C# on: Sun, Dec 27, 2009, 03:05:24 PM 
/// Using Expresso Version: 3.0.3276, http://www.ultrapico.com 
/// 
/// A description of the regular expression: 
/// 
/// [Sentence]: A named capture group. [\S.+?(?<Terminator>[.!?]|\Z)] 
///  \S.+?(?<Terminator>[.!?]|\Z) 
///   Anything other than whitespace 
///   Any character, one or more repetitions, as few as possible 
///   [Terminator]: A named capture group. [[.!?]|\Z] 
///    Select from 2 alternatives 
///     Any character in this class: [.!?] 
///     End of string or before new line at end of string 
/// Match a suffix but exclude it from the capture. [\s+|\Z] 
///  Select from 2 alternatives 
///   Whitespace, one or more repetitions 
///   End of string or before new line at end of string 
/// 
/// 
/// </summary> 
public static Regex regex = new Regex(
     "(?<Sentence>\\S.+?(?<Terminator>[.!?]|\\Z))(?=\\s+|\\Z)", 
    RegexOptions.CultureInvariant 
    | RegexOptions.IgnorePatternWhitespace 
    | RegexOptions.Compiled 
    ); 


// This is the replacement string 
public static string regexReplace = 
     "$& [${Day}-${Month}-${Year}]"; 


//// Replace the matched text in the InputText using the replacement pattern 
// string result = regex.Replace(InputText,regexReplace); 

//// Split the InputText wherever the regex matches 
// string[] results = regex.Split(InputText); 

//// Capture the first Match, if any, in the InputText 
// Match m = regex.Match(InputText); 

//// Capture all Matches in the InputText 
// MatchCollection ms = regex.Matches(InputText); 

//// Test to see if there is a match in the InputText 
// bool IsMatch = regex.IsMatch(InputText); 

//// Get the names of all the named and numbered capture groups 
// string[] GroupNames = regex.GetGroupNames(); 

//// Get the numbers of all the named and numbered capture groups 
// int[] GroupNumbers = regex.GetGroupNumbers(); 
0

Die meisten haben empfohlen, eine SharpNLP zu verwenden, und Sie sollten dies wahrscheinlich tun, es sei denn, Sie möchten, dass Ihre QA-Abteilung ein Bugfest hat.

Aber da sind Sie wahrscheinlich unter einem gewissen Druck. Hier ist ein weiterer Versuch, mit Worten wie "Dr." umzugehen und "X.". Aber es wird mit einem Satz fehlschlagen, der in "es" endet.

Hallo Welt! Wie geht es dir? Mir geht es gut. Dies ist ein schwieriger Satz , weil ich I.D. Newlines sollten ebenfalls akzeptiert werden. Zahlen sollten nicht Satzbrüche verursachen, wie 1.23. Siehe Dr. B oder Mr. FooBar für H. pylori Beurteilung in der Kardia.

var result = new Regex(@"(\S.+?[.!?])(?=\s+|$)(?<!\s([A-Z]|[a-z]){1,3}.)").Split(input).Where(s => !String.IsNullOrWhiteSpace(s)).ToArray<string>(); 
    foreach (var match in result) 
    { 
     Console.WriteLine(match); 
    } 
Verwandte Themen