Соответствие переносам строк - \n или \r\n?
Во время написания этого ответа мне приходилось сопоставлять исключительно переводы строк вместо использования s
-флаг (dotall
- точка соответствует переводу строки).
Сайты, обычно используемые для проверки регулярных выражений, ведут себя по-разному при попытке сопоставления на \n
или же \r\n
,
Я заметил
Regex101 соответствует разрывам строк только на
\n
( пример - удалить\r
и это совпадает)RegExr не соответствует разрывам строк ни на
\n
ни на\r\n
и я не могу найти что-то, чтобы это соответствовало разрыву строки, кромеm
-флаг и\s
( пример)Debuggex ведет себя еще более по-разному:
в этом примере это соответствует только на\r\n
, в то время как
здесь это только соответствует\n
с такими же флагами и указанным двигателем
Я полностью осведомлен о m
-флаг (многострочный - делает ^
соответствовать началу и $
конец строки), но иногда это не вариант. То же самое с \s
, так как он совпадает с табуляцией и пробелами тоже.
Моя мысль использовать символ перевода строки Unicode (\u0085
) не удалось, так что:
- Есть ли надежный способ интегрировать совпадение на разрыв строки (желательно независимо от используемого языка) в регулярное выражение?
- Почему вышеупомянутые сайты ведут себя по-разному (особенно Debuggex, сопоставляя только один раз на
\n
и только один раз на\r\n
)?
7 ответов
Собираюсь ответить в обратном направлении;)
2) Для полного объяснения \ r и \ n я должен обратиться к этому вопросу, который является гораздо более полным, чем я опубликую здесь: Разница между \ n и \r?
Короче говоря, Linux использует \ n для новой строки, Windows \r\n и старых Macs \r. Так что есть несколько способов написать новую строку. Ваш второй инструмент (RegExr), например, сопоставляет одиночный \ r.
1) [\r\n]+
как предположил Илья, будет работать, но также будет соответствовать нескольким последовательным новым строкам. (\r\n|\r|\n)
правильнее
У вас есть разные окончания строк в текстах примеров в Debuggex. Что особенно интересно, так это то, что Debuggex определил, какой стиль окончания строки вы использовали первым, и он преобразует все дополнительные окончания строки, введенные в этот стиль.
Я использовал Notepad++ для вставки образца текста в формате Unix и Windows в Debuggex, и что бы я ни вставил первым, это то, с чем застрял этот сеанс Debuggex.
Итак, вы должны вымыть свой текст через текстовый редактор, прежде чем вставлять его в Debuggex. Убедитесь, что вы вставляете стиль, который хотите. По умолчанию в Debuggex используется стиль Unix (\n).
Кроме того, NEL (\u0085) - это нечто совершенно иное: https://en.wikipedia.org/wiki/Newline
(\r?\n)
будет охватывать Unix и Windows. Вам нужно что-то более сложное, как (\r\n|\r|\n)
, если вы хотите соответствовать старому Mac тоже.
Не уверен, что это то, о чем просили:
(somethingToStaMatch)(.|\n)*?(somethingToEndMatch)
Это будет иметь 3 группы матчей. И ALLWITHLINEBREAKS посередине. Может помочь кому-то протестированному с dotnet.
строковый шаблон = @"(somethingToStartMatch)(.|\n)*?(somethingToEndMatch)";
Обратите внимание, что
*?
позволяет сопоставлять, даже если ваш текст имеет несколько пар ключевых слов!
В Python:
# as Peter van der Wal's answer
re.split(r'\r\n|\r|\n', text, flags=re.M)
или более строгое:
# https://docs.python.org/3/library/stdtypes.html#str.splitlines
str.splitlines()
Это относится только к вопросу 1.
У меня есть приложение, которое работает в Windows и использует многострочный редактор MFC.
В окне редактора ожидаются разрывы строк CRLF, но мне нужно разобрать введенный текст
с некоторыми действительно большими / противными регулярными выражениями.
Я не хотел подчеркивать это во время написания регулярного выражения, поэтому
Я закончил нормализацию парсера и редактора, чтобы
регулярные выражения просто использовать \n
, Я также отлавливаю операции вставки и конвертирую их для блоков.
Это не займет много времени.
Это то, что я использую.
boost::regex CRLFCRtoLF (
" \\r\\n | \\r(?!\\n) "
, MODx);
boost::regex CRLFCRtoCRLF (
" \\r\\n?+ | \\n "
, MODx);
// Convert (All style) linebreaks to linefeeds
// ---------------------------------------
void ReplaceCRLFCRtoLF( string& strSrc, string& strDest )
{
strDest = boost::regex_replace ( strSrc, CRLFCRtoLF, "\\n" );
}
// Convert linefeeds to linebreaks (Windows)
// ---------------------------------------
void ReplaceCRLFCRtoCRLF( string& strSrc, string& strDest )
{
strDest = boost::regex_replace ( strSrc, CRLFCRtoCRLF, "\\r\\n" );
}
Немного опоздал на вечеринку, но в остальном может быть, возможно, полезен. В javascript вы можете просто написать канал (
|
), чтобы соответствовать символам новой строки/разрыву строки. В моем случае мне нужно было избавиться от всех запятых, точек с запятой и пробелов (включая разрывы строк), поэтому в итоге я использовал это:
.split(/[\s,;|]+/)