2015-09-07 3 views
0

Моя задача - выбрать первое предложение из текста (пишу в C#). Я полагаю, что наиболее подходящим способом будет использование regex, но возникли некоторые проблемы. Какой шаблон регулярного выражения следует использовать для выбора первого предложения?Как выбрать первое предложение в тексте, используя регулярное выражение?

Несколько примеров:

  1. Входной сигнал: «? Я лев, и я хочу быть свободным Вы видите лев, когда вы смотрите внутри меня» Ожидаемый результат: «Я лев, и я хочу быть свободным».
  2. Ввод: «Я пью так много, что они называют меня Чарли 4.0 руками. Любой текст». Ожидаемый результат: «Я пью так много, что они называют меня Чарли 4.0 руками».
  3. Вход: «Так что вытащите руки и выбросьте Х. вверх». Теперь взведите его вокруг, как будто вы не подделываете! »« Ожидаемый результат: «Так что вытащите руки и выбросьте Х.У.».

Третий действительно меня смущает.

+1

Что регулярное выражение шаблон не вы пробовали до сих пор? – HubertL

+0

Что делать, если скелеты «склеены»? Как «Я лев, и я хочу быть свободным. Ты видишь льва, когда ты заглядываешь в меня?» Я могу предоставить регулярное выражение для текущих предложений, но опять же, как насчет «Некоторые предложения». iPad ... '? –

+0

Я сомневаюсь, что существует надежный способ сделать это через все законные английские предложения. Вы можете довольно легко написать небольшую логику, которая будет доступна в 99% случаев. – Jonesopolis

ответ

1

Поскольку вы aleready представили некоторые предположения:

предложения разделены пробелами
задачей является выбрать первое предложение

Вы можете использовать следующее регулярное выражение:

^.*?[.?!](?=\s+(?:$|\p{P}*\p{Lu})) 

См RegexStorm demo

Regex пробой:

  • ^ - начало строки (таким образом, только первое предложение будет сопоставляться)
  • .*? - любое количество символов, как мало (используйте RegexOptions.Singleline, чтобы также соответствовать новой строке с .)
  • [.?!] - окончательная пунктуация символ
  • (?=\s+(?:$|\p{P}*\p{Lu})) - взгляд вперед убедившись, что есть 1 или более пробельные символы (\s+) сразу после того, до конца строки ($) или опциональной пунктуации (\p{P}) и букв (\p{Lu}).

UPDATE:

Так получается, что вы можете иметь один вход приговор, и ваши предложения могут начинаться с любой буквы или цифры, вы можете использовать

^.*?[.?!](?=\s+\p{P}*[\p{Lu}\p{N}]|\s*$) 

См another demo

+0

Надеюсь, что это будет хотя бы полезно. –

+2

Отличный ответ , хотя это не соответствует, когда в тексте есть только одно предложение (без конечных пробелов). Его можно решить с помощью '^. *? [.?!] (? = \ s + \ p {P} * \ p {Lu} | \ s * $) ' – Mariano

+0

На самом деле, я думал, что существует другое предположение: на входе должно быть не менее двух предложений. –

-1

Я придумал регулярное выражение, которое использует множество негативных ожиданий, чтобы исключить определенные случаи, например. пунктуация должна не сопровождаться строчным символом или точкой до того, как заглавная буква не закрывает предложение. Это разделяет весь текст в их отдельных предложениях. Если вам дан текст, просто возьмите первый матч.

[\s\S]*?(?![A-Z]+)(?:\.|\?|\!)(?!(?:\d|[A-Z]))(?! [a-z])/gm

regex

+0

Это вопрос, связанный с C#, а не JavaScript. И вам нужно больше узнать о классах символов, чтобы писать более оптимальные шаблоны.' (?: \ d | [AZ]) 'или '(?: \. | \? | \!)' не эффективны по сравнению с '[\ dA-Z]' и '[?!.]'. –

-1

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

  • если это sentence-finisher характер
    • он должен сопровождаться пробелом или разрешенная последовательность символов, а затем пространство (например, [.!?]): ''
      • как последовательность для '.' (A sentence...)
      • ... или последовательность '!' и/или '?' для '!' а также '?' (Exclamation here!?)
    • , то она должна сопровождаться либо:
      • капитального характера (игнорировать кавычки, если таковые имеются)
      • числовая
        • который должен следовать строчными или другой sentence-finister
      • dialog-starter персонаж (Blah blah blah... - And what next, Elric?)

Совет: не забудьте добавить дополнительный пробел к исходной строке ввода.

Upd:

Некоторые дикие псевдокод XD:

func sentence(inputString) { 
    finishers = ['.', '!', '?'] 

    allowedSequences = ['.' => ['..'], '!' => ['!!', '?'], '?' => ['??', '!']] 

    input = inputString 
    result = '' 

    found = false 
    while input != '' { 

     finisherPos = min(pos(input, finishers)) 

     if !finisherPos 
      return inputString 

     result += substr(input, 0, finisherPos + 1) 
     input = substr(input, finisherPos) 

     p = finisherPos 

      finisher = input[p] 

      p++ 

      if input[p] != ' ' 
       if match = testSequence(substr(input, p), allowedSequences[finisher]) { 
        result += match 
        found = true 
        break 
       } else { 
        continue 
       } 
      else { 
       p++ 
       if input[p] in [A-Z] { 
        found = true 
        break 
       } 

       if input[p] in [0-9] { 
        p++ 
        if input[p] in [a-z] or input[p] in finishers { 
         found = true 
         break 
        } 
        p-- 
       } 

       if input[p] in ['-'] { 
        found = true; 
        break 
       } 
      } 

    } 

    if !found 
     return inputStr 

    return result 
} 

func testSequence(str, sequences) { 
    foreach (sequence: sequences) 
     if startsWith(str, sequence) 
      return sequence 

    return false 
} 
Смежные вопросы