2013-09-20 4 views
17

В настоящее время я работаю над приложением, которое разбивает длинный столбец на короткие. Для этого я разделяю весь текст на слова, но в настоящее время мое регулярное выражение также разделяет числа.Разделить строку на предложения в javascript

Что я сделать это:

str = "This is a long string with some numbers [125.000,55 and 140.000] and an end. This is another sentence."; 
sentences = str.replace(/\.+/g,'.|').replace(/\?/g,'?|').replace(/\!/g,'!|').split("|"); 

Результат:

Array [ 
    "This is a long string with some numbers [125.", 
    "000,55 and 140.", 
    "000] and an end.", 
    " This is another sentence." 
] 

Желаемый результат будет:

Array [ 
    "This is a long string with some numbers [125.000, 140.000] and an end.", 
    "This is another sentence" 
] 

Как я должен изменить регулярное выражение добиться этого? Нужно ли мне следить за некоторыми проблемами, с которыми я мог столкнуться? Или было бы достаточно, чтобы найти ". ", "? " и "! "?

+0

Можете ли вы изменить строку или это не вариант? – Beejee

+0

Вы ищете рабочее регулярное выражение, которое получило бы желаемый результат (или), который вы уже знаете, и хотите, чтобы предложения по другим потенциальным проблемам с ним? – Harry

+0

@Beejee: Я мог бы манипулировать струной. –

ответ

21
str.replace(/([.?!])\s*(?=[A-Z])/g, "$1|").split("|") 

Выход:

[ 'This is a long string with some numbers [125.000,55 and 140.000] and an end.', 
    'This is another sentence.' ] 

Разбивка:

([.?!]) = Захват либо . или ? или !

\s* = Захват 0 или более пробельные символы после предыдущего маркера ([.?!]). Это означает пробелы, следующие за знаками пунктуации, которые соответствуют грамматике английского языка.

(?=[A-Z]) = Предыдущие токены соответствуют только следующему символу в диапазоне A-Z (капитал A в капитал Z). Большинство предложений на английском языке начинаются с заглавной буквы. Это не учитывает ни одно из предыдущих регулярных выражений.


ЗАМЕНИТЬ операция использует:

"$1|" 

Мы использовали один «захватив группу» ([.?!]) и мы захватить один из этих символов, и заменить его $1 (матч) плюс |. Итак, если мы захватили ?, то замена будет ?|.

И наконец, мы разделим трубы | и получим наш результат.


Так, по существу, то, что мы говорим, это:

1) Найти знаки препинания (один из . или ? или !) и захватить их

2) Знаки препинания может необязательно включать в себя после них.

3) После знака препинания я ожидаю прописную букву.

В отличие от предыдущих регулярных выражений, это соответствовало бы грамматике английского языка.

Оттуда:

4) Заменит захваченные знаки препинания, прилагая трубу |

5) разобьет трубу, чтобы создать массив предложений.

+0

Это решение выходит из строя, если предложение начинается с числа. – Tibos

+0

Вы можете изменить его следующим образом: /([.?!])\x20{1,2}(?=[A-Z\d])/.Тем не менее, это будет означать, что A) десятичные числа не имеют пробелов после них, а B) есть один или два пробела после знака препинания. Это соответствовало бы английской грамматике. Если вы не можете согласиться с условием A, в грамматике, которую вы пытаетесь разобрать, была бы двусмысленность. –

+0

Подробнее о грамматической двусмысленности в информатике: http://en.wikipedia.org/wiki/Ambiguous_grammar. По существу, в вашей ситуации цифры с десятичным разделителем и знаки препинания для новых предложений должны быть грамматически различимыми. Пересмотренное регулярное выражение, которое я предоставил, соответствует грамматике английского языка. –

4

Используйте предпросмотр, чтобы избежать замены точки, если не следует пробел + слово знак:

sentences = str.replace(/(?=\s*\w)\./g,'.|').replace(/\?/g,'?|').replace(/\!/g,'!|').split("|"); 

ВЫВОД:

["This is a long string with some numbers [125.000,55 and 140.000] and an end. This is another sentence."] 
4

Вы безопаснее с помощью предпросмотр, чтобы убедиться, что следует после того, как точка не цифра.

var str ="This is a long string with some numbers [125.000,55 and 140.000] and an end. This is another sentence." 

var sentences = str.replace(/\.(?!\d)/g,'.|'); 
console.log(sentences); 

Если вы хотите быть еще более безопасным вы могли бы проверить, что за это цифра, как хорошо, но так как JS не поддерживает назад ', вам нужно захватить предыдущий символ и использовать его в строке заменить ,

var str ="This is another sentence.1 is a good number" 

var sentences = str.replace(/\.(?!\d)|([^\d])\.(?=\d)/g,'$1.|'); 
console.log(sentences); 

Еще более простое решение, чтобы избежать точек внутри чисел (заменить их $$$$, например), сделайте раскол и после экранирования в точки.

+0

Это единственное, что отлично сработало для меня. (первая версия) –

5

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

.*?(?:\.|!|\?)(?:(?= [A-Z0-9])|$) 

Regular expression visualization

Debuggex Demo

Он разбивает этот текст

This is a long string with some numbers [125.000,55 and 140.000] and an end. This is another sentence. Sencenes beginning with numbers work. 10 people like that. 

в предложениях:

This is a long string with some numbers [125.000,55 and 140.000] and an end. 
This is another sentence. 
Sencenes beginning with numbers work. 
10 people like that. 

jsfiddle

+0

Это замечательно, я только заметил, что он не обрабатывает плохой ввод пользователя, например, «Джим пошел в магазин. Ларри спал до 12. Но Бекки уехал на выходные». Но это выходит за рамки вопроса. Я просто упоминаю об этом для тех, кто, как и я, может искать быстрое регулярное выражение, чтобы справиться с этим. –

3

Вы забыли поместить '\ s' в свое регулярное выражение.

попробовать это один

var str = "This is a long string with some numbers [125.000,55 and 140.000] and an end. This is another sentence."; 
var sentences = str.replace(/\.\s+/g,'.|').replace(/\?\s/g,'?|').replace(/\!\s/g,'!|').split("|"); 
console.log(sentences[0]); 
console.log(sentences[1]); 

http://jsfiddle.net/hrRrW/

3

Я бы просто изменить строки и положить что-то между каждым предложением. Вы сказали, что имеете право изменить их, так что будет легче сделать это так.

\r\n 

При этом у вас есть строка для поиска, и вам не нужно будет использовать это сложное регулярное выражение.

Если вы хотите сделать это, тем сложнее я буду использовать регулярное выражение для поиска "." "?" "!" озаглавленной большой буквы. Как Тесси показал тебе.

8
str.replace(/(\.+|\:|\!|\?)(\"*|\'*|\)*|}*|]*)(\s|\n|\r|\r\n)/gm, "$1$2|").split("|") 

RegExp (см на Debuggex):

  • (+ |:.! | | \) "" = Приговор может закончиться не только, "!" или, но и "..." или ":" "?"
  • (\»| \» |) * |} |]) = Приговор может быть окружен quatation знаками или скобка
  • (\ S | \ п | \ г | \ г \ п) = После sentense должен быть пробел или конец строки
  • г = глобальная
  • м = многострочный

Примечания:

  • Если вы используете (? = [A-Z]), RegExp будет работать некорректно на некоторых языках. Например. «Ü», «Č» или «Á» не будут распознаны.
Смежные вопросы