Ниже приведено решение с частичным регулярным выражением, которое игнорирует терминаторы предложений, которые содержатся между двойными кавычками.
код
def extract_sentences(str, da_terminators)
start_with_quote = (str[0] == '"')
str.split(/(\".*?\")/)
.flat_map.with_index { |b,i|
(start_with_quote == i.even?) ? b : b.split(/([#{da_terminators}])/) }
.slice_after(/^[#{da_terminators}]$/)
.map { |sb| sb.join.strip }
end
Пример
puts extract_sentences(str, '!?.')
# My friend said "John isn't here!", then "I'm outta' here" and then he left.
# Let's go!
# Later, he said "Aren't you coming?"
Объяснение
str
Для выше и
da_terminators = '!?.'
Нам необходимо следующее позже:
start_with_quote = (str[0] == '"')
#=> false
Разделить строку на "..."
. Мы должны сделать \".*?\"
группой захвата, чтобы сохранить ее в split
. Результатом является массив, block
, который поочередно имеет строки, окруженные двойными кавычками и другими строками. start_with_quote
рассказывает нам, что есть.
blocks = str.split(/(\".*?\")/)
#=> ["My friend said ",
# "\"John isn't here!\"",
# ", then ",
# "\"I'm outta' here\"",
# " and then he left. Let's go! Later, he said ",
# "\"Aren't you coming?\""]
Разделить элементы строки, которые не окружены двойными кавычками. Разделение происходит на любом из символов, заканчивающих предложение. Опять же, это должно быть в группе захвата, чтобы сохранить разделитель.
new_blocks = blocks.flat_map.with_index { |b,i|
(start_with_quote == i.even?) ? b : b.split(/([#{da_terminators}])/) }
#=> ["My friend said ",
# "\"John isn't here!\"",
# ", then ",
# "\"I'm outta' here\"",
# " and then he left",
# ".",
# " Let's go",
# "!",
# " Later, he said ",
# "\"Aren't you coming?\""
sentence_blocks_enum = new_blocks.slice_after(/^[#{da_terminators}]$/)
# #<Enumerator:0x007f9a3b853478>
Convert это переписчик в массив, чтобы увидеть, что он будет проходить в его блок:
sentence_blocks_enum.to_a
#=> [["My friend said ",
# "\"John isn't here!\"",
# ", then ",
# "\"I'm outta' here\"",
# " and then he left", "."],
# [" Let's go", "!"],
# [" Later, he said ", "\"Aren't you coming?\""]]
Объединить блоки каждого предложения и strip
пробелов и возвращает массив:
sentence_blocks_enum.map { |sb| sb.join.strip }
#=> ["My friend said \"John isn't here!\", then \"I'm outta' here\" and then he left.",
# "Let's go!",
# "Later, he said \"Aren't you coming?\""]
Рассмотрите: «Джек хороший мальчик, я уверен, что он!». Один или два предложения? Возможно, вам нужно только учитывать двойные кавычки. –
@CarySwoveland Хорошая точка. Как бы вы решили заняться что, чтобы каждое предложение было чистым? Я использую Википедию в качестве источников, а затем извлекаю предложения для тестирования детей на пунктуацию. –
Я не вижу, как вы можете определить разрывы предложений, где терминатор находится между одинарными кавычками. Можете ли вы относиться только к двойным кавычкам? –