Соответствие переносам строк - \ n или \ r \ n?

159

При написании этого ответа мне приходилось сопоставлять исключительно sразрывы строк вместо использования -flag ( dotall- точка соответствует разрывам строк ).

Сайты, обычно используемые для проверки регулярных выражений, ведут себя по-разному при попытке сопоставления с \nили \r\n.

я отметил

  • Regex101 сопоставляет только разрывы строк \n
    ( пример - удалить, \rи это соответствует)

  • RegExr соответствует переносы строк ни на , \n ни на , \r\n
    и я не могу найти что - то , чтобы сделать его соответствовать разрыв строки, за исключением той m-flag и \s
    ( например )

  • Debuggex ведет себя еще более по-разному:
    в этом примере он совпадает только с \r\n, в то время как
    здесь он только с \n, с теми же флагами и указанным движком

Я полностью осведомлен о mфлаге (многострочный - ^сопоставляет начало и $конец строки), но иногда это не вариант. То же самое с тем \s, что он также соответствует символам табуляции и пробелов.

Моя мысль использовать символ новой строки ( \u0085) в Юникоде не удалась, поэтому:

  1. Есть ли надежный способ интегрировать совпадение на разрыв строки (желательно независимо от используемого языка) в регулярное выражение?
  2. Почему вышеупомянутые сайты ведут себя по-разному (особенно Debuggex, сопоставляя только \nодин раз и только один раз \r\n)?
KeyNone
источник
15
Вы можете попробовать [\r\n]+- или что-то вроде этого
Илья Бурсов
3
Я использую: \r?\nчтобы соответствовать обе последовательности \r\nи \nпоследовательности завершения строки. Это не работает для старого \rсинтаксиса Mac, но этот довольно редкий в наши дни.
Ridgerunner
6
Привет, я основатель debuggex. Это похоже на ошибку (для debuggex я не могу говорить за других). Я добавил проблему высокого уровня, ссылающуюся на этот вопрос. Мы доберемся до него как можно скорее - в настоящее время мы сосредоточиваем все наши (очень ограниченные) ресурсы на запуске другого продукта.
Серджиу Тоарка
2
@ridgerunner, чтобы добавить к этому синтаксис Mac, вы можете это сделать (\ r? \ n | \ r), что похоже на ответ Питера ван дер Вала ниже, но более компактно (10 символов против 12 символов).
Доктор Дж

Ответы:

220

Собираюсь ответить в обратном направлении.

2) Для полного объяснения \rи \nя должен обратиться к этому вопросу, который является гораздо более полным, чем я опубликую здесь: Разница между \ n и \ r?

Короче говоря, Linux использует \nдля новой линейки, Windows \r\nи старых Mac \r. Так что есть несколько способов написать новую строку. Ваш второй инструмент (RegExr), например, соответствует на сингле \r.

1) [\r\n]+как предположил Илья, будет работать, но также будет соответствовать нескольким последовательным новым строкам. (\r\n|\r|\n)правильнее

Питер ван дер Валь
источник
Итак, \r/ \nзависят от операционной системы - это вещь, которую можно знать (;)) - но почему два примера отладки совпадают один раз на \ r \ n и один раз на \ n? По крайней мере, нет никакой разницы (в примерах), видимой для меня.
KeyNone
Скорее всего потому, что вы скопировали один из текстового редактора Windows, а другой - прямо в текстовое поле debuggex. Каждый использовал разные разрывы строк.
О.Г.Газа
1
Действительно, потому что в вашем третьем примере (Старший мужчина ...) есть \r\nтекст (если вы щелкните правой кнопкой мыши и покажете источник, вы найдете {{Infobox XC Championships\r\n|Name =где-нибудь). Второй инструмент написан на Flash, и когда вы читаете страницу с информацией о программе, она содержит ошибки в символах перевода строки.
Питер ван дер Валь
1
(\r\n|\r|\n)можно записать проще\r\n?
Асад Саидуддин
2
@AsadSaeeduddin Нет, не может. Это не будет соответствовать окончанию строки Unix\n
Питер ван дер Валь
12

У вас есть разные окончания строк в текстах примеров в Debuggex. Что особенно интересно, Debuggex, похоже, определил, какой стиль окончания строки вы использовали первым, и он преобразует все дополнительные окончания строки, введенные в этот стиль.

Я использовал Notepad ++ для вставки образца текста в формате Unix и Windows в Debuggex, и что бы я ни вставил первым, это то, с чем застрял этот сеанс Debuggex.

Итак, вы должны вымыть свой текст через текстовый редактор, прежде чем вставлять его в Debuggex. Убедитесь, что вы вставляете стиль, который вы хотите. По умолчанию в Debuggex используется стиль Unix (\ n).

Кроме того, NEL (\ u0085) - это нечто совершенно иное: https://en.wikipedia.org/wiki/Newline#Unicode

(\r?\n)будет охватывать Unix и Windows. Вам нужно что-то более сложное, например (\r\n|\r|\n), если вы хотите соответствовать старому Mac тоже.

датчанин
источник
Очень интересный момент о Debuggex! Также, спасибо за то, что указал на \ u0085, заблуждалась там!
KeyNone
3

В PCRE \Rсоответствует \n, \rи \r\n.

Cwazy Paving
источник
Там нет вопросов
Сандвелл
1
@Sandwell: Извините, я вас не понимаю, это не вопрос, это ответ, более простой, чем(\r\n|\r|\n)
Тото
2

Это относится только к вопросу 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" );
 }

источник
2

В 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()
Килунг
источник