Faire correspondre les sauts de ligne - \ n ou \ r \ n?

159

Lors de la rédaction de cette réponse , je devais correspondre exclusivement aux sauts de ligne au lieu d'utiliser le s-flag ( dotall- le point correspond aux sauts de ligne).

Les sites généralement utilisés pour tester les expressions régulières se comportent différemment lors de la tentative de correspondance sur \nou \r\n.

j'ai remarqué

  • Regex101 correspond aux sauts de ligne uniquement sur \n
    ( exemple - supprimer \ret cela correspond)

  • RegExr ne correspond aux sauts de ligne ni sur \n ni sur \r\n
    et je ne trouve pas quelque chose pour le faire correspondre à un saut de ligne, sauf pour le m-flag et \s
    ( exemple )

  • Debuggex se comporte encore plus différemment:
    dans cet exemple, il ne correspond qu'à on \r\n, alors
    qu'ici il ne correspond qu'à on \n, avec les mêmes indicateurs et moteur spécifiés

Je suis pleinement conscient du m-flag (multiligne - fait ^correspondre le début et $la fin d'une ligne), mais parfois ce n'est pas une option. Idem avec \s, car il correspond également aux tabulations et aux espaces.

Ma pensée d'utiliser le caractère de nouvelle ligne unicode ( \u0085) n'a pas abouti, donc:

  1. Existe-t-il un moyen sûr d'intégrer la correspondance sur un saut de ligne (de préférence quelle que soit la langue utilisée) dans une expression régulière?
  2. Pourquoi les sites mentionnés ci-dessus se comportent-ils différemment (en particulier Debuggex, correspondant une seule \nfois et une seule fois \r\n)?
KeyNone
la source
15
Vous pouvez essayer [\r\n]+- ou quelque chose comme ça
Iłya Bursov
3
J'utilise: \r?\nfaire correspondre les deux \r\net les \nséquences de terminaison de ligne. Cela ne fonctionne pas pour l'ancienne \rsyntaxe Mac, mais celle-ci est assez rare de nos jours.
ridgerunner
6
Salut, je suis le fondateur de debuggex. Cela ressemble à un bug (pour debuggex, je ne peux pas parler pour les autres). J'ai ajouté un problème élevé faisant référence à cette question. Nous y arriverons dès que possible - nous concentrons actuellement toutes nos ressources (très limitées) sur le lancement d'un autre produit.
Sergiu Toarca
2
@ridgerunner pour ajouter la syntaxe de Mac à cela, vous pouvez faire (\ r? \ n | \ r), qui est similaire à la réponse de Peter van der Wal ci-dessous mais plus compacte (10 caractères contre 12 caractères).
Doktor J

Réponses:

220

Je vais répondre dans la direction opposée.

2) Pour une explication complète \ret \nje dois me référer à cette question, qui est beaucoup plus complète que je ne posterai ici: Différence entre \ n et \ r?

Bref, Linux utilise \npour une nouvelle ligne, Windows \r\net les anciens Mac \r. Il existe donc plusieurs façons d'écrire une nouvelle ligne. Votre deuxième outil (RegExr) correspond par exemple sur le single \r.

1) [\r\n]+comme Ilya l'a suggéré fonctionnera, mais correspondra également à plusieurs nouvelles lignes consécutives. (\r\n|\r|\n)est plus correct.

Peter van der Wal
la source
Donc, \r/ \ndépendent du système d'exploitation - c'est une chose que l'on sait (;)) - mais pourquoi les deux exemples de debuggex correspondent-ils une fois sur \ r \ n et une fois sur \ n? Au moins, il n'y a aucune différence (dans les exemples) visible pour moi.
KeyNone
Très probablement parce que vous en avez copié un hors de votre éditeur de texte Windows et l'autre que vous avez écrit directement dans la zone de texte debuggex. Chacun utilisait des sauts de ligne différents.
OGHaza
1
En effet, parce que dans votre troisième exemple (les hommes seniors ...) il y a un \r\ndans le texte (si vous faites un clic droit et montrez la source, vous trouverez {{Infobox XC Championships\r\n|Name =quelque part). Le deuxième outil est écrit en Flash et lorsque vous lisez la page à propos, un peu bogué avec des caractères de nouvelle ligne.
Peter van der Wal
1
(\r\n|\r|\n)peut être écrit plus simplement comme\r\n?
Asad Saeeduddin
2
@AsadSaeeduddin Non, ce n'est pas possible. Cela ne correspondra pas à la fin de ligne Unix\n
Peter van der Wal
12

Vous avez différentes fins de ligne dans les exemples de textes dans Debuggex. Ce qui est particulièrement intéressant, c'est que Debuggex semble avoir identifié le style de fin de ligne que vous avez utilisé en premier, et il convertit toutes les fins de ligne supplémentaires entrées dans ce style.

J'ai utilisé Notepad ++ pour coller un exemple de texte au format Unix et Windows dans Debuggex, et celui que j'ai collé en premier est ce à quoi cette session de Debuggex s'est coincée.

Vous devez donc laver votre texte dans votre éditeur de texte avant de le coller dans Debuggex. Assurez-vous de coller le style que vous souhaitez. Debuggex utilise par défaut le style Unix (\ n).

En outre, NEL (\ u0085) est quelque chose de complètement différent: https://en.wikipedia.org/wiki/Newline#Unicode

(\r?\n)couvrira Unix et Windows. Vous aurez besoin de quelque chose de plus complexe, comme (\r\n|\r|\n)si vous souhaitez également faire correspondre l'ancien Mac.

Danois
la source
Point très intéressant sur debuggex! Aussi, merci d'avoir souligné \ u0085, je me suis trompé!
KeyNone
3

Dans les \Rcorrespondances PCRE \n, \ret \r\n.

Pavage Cwazy
la source
Il n'y a pas de question
Sandwell
1
@Sandwell: Désolé, je ne vous comprends pas, ce n'est pas une question, c'est une réponse, plus simple que(\r\n|\r|\n)
Toto
2

Cela s'applique uniquement à la question 1.

J'ai une application qui fonctionne sous Windows et utilise une boîte d'éditeur MFC multiligne.
La boîte de l'éditeur attend des sauts de ligne CRLF, mais je dois analyser le texte saisi
avec des expressions régulières vraiment grosses / méchantes.

Je ne voulais pas insister à ce sujet lors de l'écriture de l'expression régulière, alors
j'ai fini par normaliser entre l'analyseur et l'éditeur pour que
les expressions rationnelles soient simplement utilisées \n. Je piège également les opérations de collage et les convertis pour les boîtes.

Cela ne prend pas beaucoup de temps.
C'est ce que j'utilise.

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

la source
2

En Python:

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

ou plus rigoureux:

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