Corresponder quebras de linha - \ n ou \ r \ n?

159

Enquanto escrevia esta resposta , tive que corresponder exclusivamente em quebras de linha em vez de usar o ssinalizador -flag ( dotall- ponto corresponde a quebras de linha).

Os sites geralmente usados ​​para testar expressões regulares se comportam de maneira diferente ao tentar corresponder em \nou \r\n.

Percebi

  • O Regex101 corresponde apenas a quebras de linha em \n
    ( exemplo - excluir \re corresponde)

  • RegExr corresponde quebras de linha nem em \n nem em \r\n
    e eu não posso encontrar algo para torná-lo coincidir com uma quebra de linha, exceto para o m-flag e \s
    ( exemplo )

  • Debuggex comporta-se ainda mais diferente:
    em este exemplo ele corresponde apenas no \r\n, enquanto
    aqui só corresponde a \n, com as mesmas bandeiras e motor especificados

Estou plenamente ciente do m-flag (multiline - faz ^coincidir com o início e $o final de uma linha), mas às vezes isso não é uma opção. O mesmo \sacontece com a correspondência de tabulações e espaços também.

Meu pensamento de usar o caractere de nova linha unicode ( \u0085) não foi bem-sucedido, então:

  1. Existe uma maneira segura de integrar a correspondência em uma quebra de linha (de preferência independentemente do idioma usado) em uma expressão regular?
  2. Por que os sites mencionados acima se comportam de maneira diferente (especialmente o Debuggex, correspondendo apenas uma \nvez e apenas uma vez \r\n)?
KeyNone
fonte
15
Você pode tentar [\r\n]+- ou algo parecido com isto
Iłya Bursov
3
Eu uso: \r?\npara combinar as seqüências de terminação \r\ne de \nlinha. Não funciona para a \rsintaxe antiga do Mac, mas essa é bastante rara atualmente.
Ridgerunner
6
Olá, sou o fundador do debuggex. Parece um bug (para o debuggex, não posso falar pelos outros). Eu adicionei um problema de alto preço referenciando essa pergunta. Chegaremos a isso o mais rápido possível - no momento, estamos concentrando todos os nossos recursos (muito limitados) no lançamento de outro produto.
Sergiu Toarca
2
@ridgerunner para adicionar a sintaxe do Mac a isso, você pode fazer (\ r? \ n | \ r), que é semelhante à resposta de Peter van der Wal abaixo, mas mais compacta (10 caracteres vs 12 caracteres).
Doktor J

Respostas:

220

Vou responder na direção oposta.

2) Para uma explicação completa \re \npreciso me referir a esta pergunta, que é muito mais completa do que postarei aqui: Diferença entre \ n e \ r?

Para encurtar a história, o Linux usa \npara uma nova linha, Windows \r\ne Macs antigos \r. Portanto, existem várias maneiras de escrever uma nova linha. Sua segunda ferramenta (RegExr) corresponde, por exemplo, ao single \r.

1), [\r\n]+como sugeriu Ilya, funcionará, mas também corresponderá a várias novas linhas consecutivas. (\r\n|\r|\n)está mais correto.

Peter van der Wal
fonte
Portanto, \r/ \nestão dependendo do sistema operacional - isso é algo que se pode saber (;)) - mas por que os dois exemplos de debuggex correspondem uma vez em \ r \ n e uma vez em \ n? Pelo menos não há diferença (nos exemplos) visível para mim.
KeyNone
Provavelmente porque você copiou um do seu editor de texto do Windows e o outro que você escreveu diretamente na área de texto debuggex. Cada um deles usou quebras de linha diferentes.
OGHaza
1
De fato, porque no seu terceiro exemplo (os homens mais velhos ...) há um \r\nno texto (se você clicar com o botão direito do mouse e mostrar a fonte, encontrará {{Infobox XC Championships\r\n|Name =algum lugar). A segunda ferramenta é escrita no Flash e, à medida que você lê a página inteira, fica um pouco buggy com caracteres de nova linha.
Peter van der Wal
1
(\r\n|\r|\n)pode ser escrito de forma mais simples como\r\n?
Asad Saeeduddin 8/16
2
@AsadSaeeduddin Não, não pode. Não vai coincidir com o Unix de fim de linha\n
Peter van der Wal
12

Você tem finais de linha diferentes nos textos de exemplo no Debuggex. O que é especialmente interessante é que o Debuggex parece ter identificado qual estilo de final de linha você usou primeiro e converte todas as terminações de linha adicionais inseridas nesse estilo.

Eu usei o Notepad ++ para colar texto de exemplo no formato Unix e Windows no Debuggex, e o que eu colei primeiro foi o que aquela sessão do Debuggex travou.

Portanto, você deve lavar seu texto através do seu editor de texto antes de colá-lo no Debuggex. Certifique-se de colar o estilo desejado. O padrão Debuggex é o estilo Unix (\ n).

Além disso, o NEL (\ u0085) é algo totalmente diferente: https://en.wikipedia.org/wiki/Newline#Unicode

(\r?\n)cobrirá o Unix e o Windows. Você precisará de algo mais complexo (\r\n|\r|\n), se quiser combinar o Mac antigo também.

dinamarquês
fonte
Ponto muito interessante sobre o debuggex! Além disso, obrigado por apontar \ u0085, foi enganado por lá!
KeyNone
3

Nos \Rjogos PCRE \n, \re \r\n.

Pavimentação Cwazy
fonte
Não há dúvida
Sandwell
1
@ Sandwell: Desculpe, eu não entendo você, isso não é uma pergunta, é uma resposta, mais simples do que(\r\n|\r|\n)
Toto
2

Isso se aplica apenas à pergunta 1.

Eu tenho um aplicativo que roda no Windows e usa uma caixa de editor MFC de várias linhas.
A caixa do editor espera quebras de linha CRLF, mas preciso analisar o texto digitado
com algumas regexs realmente grandes / desagradáveis ​​'.

Eu não queria me estressar nisso enquanto escrevia a regex, então
acabei normalizando de um lado para o outro entre o analisador e o editor, para que
as regexs apenas usassem \n. Também interto com operações de colagem e as converto para as caixas.

Isso não leva muito tempo.
É isso que eu uso.

 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" );
 }

fonte
2

Em Python:

# as Peter van der Wal's answer
re.split(r'\r\n|\r|\n', text, flags=re.M) 

ou mais rigoroso:

# https://docs.python.org/3/library/stdtypes.html#str.splitlines
str.splitlines()
Keelung
fonte