¿Qué es una expresión regular para analizar oraciones individuales?

Estoy buscando una buena expresión regular .NET que pueda usar para analizar oraciones individuales de un cuerpo de texto.

Debería ser capaz de analizar el siguiente bloque de texto en exactamente seis oraciones:

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

Esto está resultando un poco más desafiante de lo que originalmente pensé.

Cualquier ayuda sería muy apreciada. Voy a usar esto para entrenar el sistema en cuerpos de texto conocidos.

Pruebe esto @"(\S.+?[.!?])(?=\s+|$)" :

 string str=@"Hello world! How are you? I am fine. This is a difficult sentence because I use ID 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); } 

Resultados:

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

Para los complicados, por supuesto, necesitarás un analizador real como SharpNLP o NLTK. El mío es solo uno rápido y sucio.

Aquí está la información de SharpNLP , y características:

SharpNLP es una colección de herramientas de procesamiento de lenguaje natural escritas en C #. Actualmente proporciona las siguientes herramientas NLP:

  • un separador de oraciones
  • un tokenizer
  • un etiquetador de voz parcial
  • un chunker (usado para “encontrar anotaciones sintácticas no recursivas como fragmentos de frases nominales”)
  • un analizador
  • un buscador de nombres
  • una herramienta de correferencia
  • una interfaz para la base de datos léxico de WordNet
 var str = @"Hello world! How are you? I am fine. This is a difficult sentence because I use ID Newlines should also be accepted. Numbers should not cause sentence breaks, like 1.23."; Regex.Split(str, @"(?<=[.?!])\s+").Dump(); 

Probé esto en LINQPad.

Es imposible usar expresiones regulares para analizar el lenguaje natural. ¿Cuál es el final de una oración? Un período puede ocurrir en muchos lugares (egeg). Debe utilizar un kit de herramientas de análisis de lenguaje natural como OpenNLP o NLTK. Desafortunadamente, hay muy pocas ofertas en C #. Por lo tanto, puede tener que crear un servicio web o vincularlo a C #.

Tenga en cuenta que causará problemas en el futuro si confía en el espacio en blanco exacto como en “ID”. Pronto encontrará ejemplos que rompen su expresión regular. Por ejemplo, la mayoría de las personas ponen espacios después de sus iniciales.

Existe un excelente resumen de ofertas abiertas y comerciales en WP ( http://en.wikipedia.org/wiki/Natural_language_processing_toolkits ). Hemos usado varios de ellos. Vale la pena el esfuerzo.

[Usas la palabra “tren”. Esto se asocia normalmente con el aprendizaje automático (que es un enfoque de NLP y se ha utilizado para dividir oraciones). De hecho, los kits de herramientas que he mencionado incluyen aprendizaje automático. Sospecho que eso no era lo que querías decir, sino que desarrollarías tu expresión a través de la heurística. ¡No!]

Esto no es posible solo con expresiones regulares, a menos que sepa exactamente qué fichas “difíciles” tiene, como “id”, “Mr.”, etc. Por ejemplo, cuántas oraciones es “Por favor muestre su ID, Sr. Enlace.”? No estoy familiarizado con ninguna implementación de C #, pero he usado el tokenizador Punkt de NLTK . Probablemente no debería ser demasiado difícil de implementar.

Usé las sugerencias que se publicaron aquí y se me ocurrió la expresión regular que intenta lograr lo que quiero hacer:

 (?\S.+?(?[.!?]|\Z))(?=\s+|\Z) 

Usé Expresso para llegar a:

 // using System.Text.RegularExpressions; ///  /// 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.+?(?[.!?]|\Z)] /// \S.+?(?[.!?]|\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 /// /// ///  public static Regex regex = new Regex( "(?\\S.+?(?[.!?]|\\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(); 

La mayoría ha aconsejado utilizar un SharpNLP y probablemente debería hacerlo a menos que desee que su departamento de control de calidad tenga una fiesta de errores.

Pero dado que probablemente estés bajo algún tipo de presión. Aquí hay otro bash de tratar con palabras como “Dr.” y “X.” Pero, fallará con una oración que termina en “eso”.

¡Hola Mundo! ¿Cómo estás? Estoy bien. Esta es una oración difícil porque uso Id. Las nuevas líneas también deben ser aceptadas. Los números no deberían causar interrupciones de frase, como 1.23. Vea al Dr. B o al Sr. FooBar para la evaluación de H. pylori en el cardia.

  var result = new Regex(@"(\S.+?[.!?])(?=\s+|$)(? !String.IsNullOrWhiteSpace(s)).ToArray(); foreach (var match in result) { Console.WriteLine(match); }