Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)\s
Попробуйте это. разделите свою строку this.You также можете проверить демо.
Наивный подход для правильных английских предложений, не начинающийся с неалфаза и не содержащий цитируемых частей речи:
import re
text = """\
Mr. Smith bought cheapsite.com for 1.5 million dollars, i.e. he paid a lot for it. Did he mind? Adam Jones Jr. thinks he didn't. In any case, this isn't true... Well, with a probability of .9 it isn't.
"""
EndPunctuation = re.compile(r'([\.\?\!]\s+)')
NonEndings = re.compile(r'(?:Mrs?|Jr|i\.e)\.\s*$')
parts = EndPunctuation.split(text)
sentence = []
for part in parts:
if len(part) and len(sentence) and EndPunctuation.match(sentence[-1]) and not NonEndings.search(''.join(sentence)):
print(''.join(sentence))
sentence = []
if len(part):
sentence.append(part)
if len(sentence):
print(''.join(sentence))
Ложное положительное расщепление может быть уменьшено путем расширения NonEndings немного. В других случаях потребуется дополнительный код. [1]
Вы никогда не достигнете совершенства при таком подходе. Но в зависимости от задачи он может просто работать «достаточно» ...
Попробуйте разбить вход в соответствии с пробелами, а не точкой или ?
, если вы сделаете это так, точка или ?
не будут напечатаны в конечном результате.
>>> import re
>>> s = """Mr. Smith bought cheapsite.com for 1.5 million dollars, i.e. he paid a lot for it. Did he mind? Adam Jones Jr. thinks he didn't. In any case, this isn't true... Well, with a probability of .9 it isn't."""
>>> m = re.split(r'(?<=[^A-Z].[.?]) +(?=[A-Z])', s)
>>> for i in m:
... print i
...
Mr. Smith bought cheapsite.com for 1.5 million dollars, i.e. he paid a lot for it.
Did he mind?
Adam Jones Jr. thinks he didn't.
In any case, this isn't true...
Well, with a probability of .9 it isn't.
Я написал это с учетом комментариев smci выше. Это подход среднего класса, который не требует внешних библиотек и не использует регулярное выражение. Это позволяет вам предоставлять список сокращений и счетов для предложений, заканчивающихся терминаторами в оболочках, таких как период и цитата: [. ",? '..]].
abbreviations = {'dr.': 'doctor', 'mr.': 'mister', 'bro.': 'brother', 'bro': 'brother', 'mrs.': 'mistress', 'ms.': 'miss', 'jr.': 'junior', 'sr.': 'senior', 'i.e.': 'for example', 'e.g.': 'for example', 'vs.': 'versus'}
terminators = ['.', '!', '?']
wrappers = ['"', "'", ')', ']', '}']
def find_sentences(paragraph):
end = True
sentences = []
while end > -1:
end = find_sentence_end(paragraph)
if end > -1:
sentences.append(paragraph[end:].strip())
paragraph = paragraph[:end]
sentences.append(paragraph)
sentences.reverse()
return sentences
def find_sentence_end(paragraph):
[possible_endings, contraction_locations] = [[], []]
contractions = abbreviations.keys()
sentence_terminators = terminators + [terminator + wrapper for wrapper in wrappers for terminator in terminators]
for sentence_terminator in sentence_terminators:
t_indices = list(find_all(paragraph, sentence_terminator))
possible_endings.extend(([] if not len(t_indices) else [[i, len(sentence_terminator)] for i in t_indices]))
for contraction in contractions:
c_indices = list(find_all(paragraph, contraction))
contraction_locations.extend(([] if not len(c_indices) else [i + len(contraction) for i in c_indices]))
possible_endings = [pe for pe in possible_endings if pe[0] + pe[1] not in contraction_locations]
if len(paragraph) in [pe[0] + pe[1] for pe in possible_endings]:
max_end_start = max([pe[0] for pe in possible_endings])
possible_endings = [pe for pe in possible_endings if pe[0] != max_end_start]
possible_endings = [pe[0] + pe[1] for pe in possible_endings if sum(pe) > len(paragraph) or (sum(pe) < len(paragraph) and paragraph[sum(pe)] == ' ')]
end = (-1 if not len(possible_endings) else max(possible_endings))
return end
def find_all(a_str, sub):
start = 0
while True:
start = a_str.find(sub, start)
if start == -1:
return
yield start
start += len(sub)
Я использовал Karl's find_all из этой записи: Найти все вхождения подстроки в Python
Если вы хотите разбить предложения на 3 периода (не уверен, что это то, что вы хотите), вы можете использовать это регулярное выражение:
blockquote>import re text = """\ Mr. Smith bought cheapsite.com for 1.5 million dollars, i.e. he paid a lot for it. Did he mind? Adam Jones Jr. thinks he didn't. In any case, this isn't true... Well, with a probability of .9 it isn't. """ sentences = re.split(r'\.{3}', text) for stuff in sentences: print(stuff)
sent = re.split('(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)(\s|[A-Z].*)',text)
for s in sent:
print s
Здесь используется регулярное выражение: (?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)(\s|[A-Z].*)
Первый блок: (?<!\w\.\w.)
: этот шаблон ищет в цикле отрицательной обратной связи (?<!)
для всех слов (\w)
, за которым следует полный запуск (\.)
, за которым следуют другие слова (\.)
Второй блок: (?<![A-Z][a-z]\.)
: этот шаблон выполняет поиск в цикле отрицательной обратной связи для чего-либо, начиная с букв верхнего регистра ([A-Z])
, а затем строчных алфавитов ([a-z])
пока не будет найдена точка (\.)
.
Третий блок: (?<=\.|\?)
: этот шаблон ищет в контуре обратной связи точки (\.)
ИЛИ вопросительный знак (\?)
Четвертый блок : (\s|[A-Z].*)
: эта модель выполняет поиск после точки или вопросительного знака из третьего блока. Он ищет пустое пространство (\s)
ИЛИ любую последовательность символов, начиная с алфавита верхнего регистра ([A-Z].*)
. Этот блок очень важен для разделения, если вход такой как
Hello world.Hi Я здесь сегодня.
blockquote>i.e. если после точки есть пробел или пробел.
Я не очень хорош в регулярных выражениях, но более простая версия «грубая сила» на самом деле выше
sentence = re.compile("([\'\"][A-Z]|([A-Z][a-z]*\. )|[A-Z])(([a-z]*\.[a-z]*\.)|([A-Za-z0-9]*\.[A-Za-z0-9])|([A-Z][a-z]*\. [A-Za-z]*)|[^\.?]|[A-Za-z])*[\.?]")
, что означает, что допустимые единицы запуска: «[AZ] или« [AZ ] Обратите внимание, что большинство регулярных выражений жадные, поэтому порядок очень важен, когда мы делаем (или). Вот почему я написал, то есть регулярное выражение, а затем пришло таких форм, как Inc.
Хорошо, так что предложения-токенизаторы - это то, на что я смотрел в деталях, используя регулярные выражения, nltk, CoreNLP. Вы в конечном итоге пишете свои собственные, и это зависит от приложения. Этот материал сложный и ценный, и люди не просто отдают свой код токенизатора. (В конечном счете, токенизация не является детерминированной процедурой, она вероятностна и также очень сильно зависит от вашего корпуса или домена, например, сообщения в социальных сетях против обзоров Yelp vs. ...)
В общем, вы не можете полагайтесь на одно непогрешимое регулярное выражение Great White, вам нужно написать функцию, которая использует несколько регулярных выражений (как положительных, так и отрицательных); также словарь аббревиатур и некоторый базовый язык, который знает, что, например, «Я», «США», «FCC», «TARP» капитализируются на английском языке.
Чтобы проиллюстрировать, насколько легко это может серьезно осложниться, попробуем написать вам эту функциональную спецификацию для детерминированного токенизатора просто решить, будет ли один или несколько периодов ('.' / '...') обозначать конец предложения или что-то еще:
function isEndOfSentence(leftContext, rightContext)
В простом (детерминированном) случае function isEndOfSentence(leftContext, rightContext)
возвращает boolean, но в более общем смысле это вероятностно: он возвращает float (уровень уверенности, что этот конкретный «.» - конец предложения).
Попробуйте следующее:
(?<!\b(?:[A-Z][a-z]|\d|[i.e]))\.(?!\b(?:com|\d+)\b)
.
, будет потерян. Вы можете записать его позже для каждого предложения, и все готово. – vks 9 September 2014 в 04:15