Подтвердить что ты не робот

Что такое регулярное выражение для разбора отдельных предложений?

Я ищу хорошее регулярное выражение .NET, которое я могу использовать для разбора отдельных предложений из текста.

Он должен иметь возможность анализировать следующий блок текста ровно на шесть предложений:

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.

Это оказалось немного сложнее, чем я думал.

Любая помощь будет принята с благодарностью. Я собираюсь использовать это для обучения системы на известных телах текста.

4b9b3361

Ответ 1

Попробуйте @"(\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);
}

Результаты:

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.

Для сложных, конечно, вам понадобится настоящий парсер, например SharpNLP или NLTK. Мой просто быстрый и грязный.

Вот информация SharpNLP и функции:

SharpNLP - это коллекция природных средства обработки языка, написанные на С#. В настоящее время он обеспечивает следующие инструменты NLP:

  • разделитель предложений
  • токенизатор
  • теггер с частичной речью
  • chunker (используется для "поиска нерекурсивных синтаксических аннотаций, таких как фрагменты существительных фразы" )
  • синтаксический анализатор
  • поиск имени
  • инструмент привязки
  • интерфейс к лексической базе данных WordNet

Ответ 2

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();

Я тестировал это в LINQPad.

Ответ 3

Невозможно использовать регулярные выражения для анализа естественного языка. Каков конец предложения? Период может происходить во многих местах (например, например). Вы должны использовать набор инструментов для анализа естественного языка, такой как OpenNLP или NLTK. К сожалению, предложений С# в предложениях очень мало. Поэтому вам может потребоваться создать веб-сервис или иным образом связать его с С#.

Обратите внимание, что это вызовет проблемы в будущем, если вы полагаетесь на точные пробелы, как в "I.D.". Вы скоро найдете примеры, которые нарушают ваше регулярное выражение. Например, большинство людей помещают пробелы после их намеков.

Существует отличное резюме открытых и коммерческих предложений в WP (http://en.wikipedia.org/wiki/Natural_language_processing_toolkits). Мы использовали несколько из них. Это стоит усилий.

[Вы используете слово "поезд". Обычно это связано с машинным обучением (которое является одним из подходов к НЛП и используется для разделения предложений). В самом деле, упомянутые мною инструментальные средства включают в себя машинное обучение. Я подозреваю, что это было не то, что вы имели в виду, а скорее, что вы будете выражать свое выражение через эвристику. Не]

Ответ 4

Это невозможно сделать только с регулярными выражениями, если вы точно не знаете, какие "трудные" токены у вас есть, например "id", "Mr." и т.д. Например, сколько предложений "Пожалуйста, покажите свой идентификатор, Г-н Бонд."? Я не знаком с любыми реализациями С#, но я использовал NLTK Punken tokenizer. Вероятно, это не должно быть слишком сложно для повторного внедрения.

Ответ 5

Я использовал предложения, размещенные здесь, и придумал регулярное выражение, которое швы для достижения того, что я хочу сделать:

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

Я использовал Expresso, чтобы придумать:

//  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();

Ответ 6

Большинство советовали использовать SharpNLP, и вам, вероятно, следует это сделать, если вы не хотите, чтобы ваш отдел QA имел жуткий праздник.

Но поскольку вы, вероятно, находитесь под каким-то давлением. Вот еще одна попытка разобраться со словами типа "Доктор" и "X.". Но это не сработает с предложением, заканчивающимся на "это".

Привет, мир! Как дела? Я в порядке. Это трудное предложение потому что я использую I.D. Также должны быть приняты новые строки. Номера не должны вызывают разрывы предложений, например, 1.23. См. Dr. B или Mr. FooBar для H. pylori оценка в кардии.

    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);
    }