web-dev-qa-db-fra.com

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

En écrivant cette réponse , je devais faire correspondre exclusivement les sauts de ligne au lieu d'utiliser l'indicateur s- (dotall - les points correspondent aux sauts de ligne). 

Les sites généralement utilisés pour tester les expressions régulières se comportent différemment lorsque vous tentez de faire correspondre les caractères \n ou \r\n.

J'ai remarqué

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

  • RegExr correspond aux sauts de ligne ni sur \nni sur \r\n
    et je ne trouve rien qui puisse le faire correspondre à un saut de ligne, à l'exception de l'indicateur m- et de \s
    ( Exemple )

  • Debuggex se comporte encore plus différemment:
    dans cet exemple il correspond uniquement à \r\n, alors que
    here il ne correspond que sur \n, avec les mêmes drapeaux et le même moteur que ceux spécifiés

Je connais parfaitement le drapeau m- (multiligne - permet à ^ de correspondre au début et $ à la fin d'une ligne), mais parfois ce n'est pas une option. Idem avec \s, car il correspond aussi aux tabulations et aux espaces. 

Mon idée d'utiliser le caractère de nouvelle ligne unicode ( \u0085 ) n'a pas abouti.

  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, une seule correspondance sur \n et une seule fois sur \r\n)?
94
Basti M

Va répondre dans le sens opposé;)

2) Pour une explication complète sur\r et\n, je dois me référer à cette question, qui est bien plus complète que ce que je vais poster ici: Différence entre\n et\r?

En bref, Linux utilise\n pour créer une nouvelle ligne, Windows\r et les anciens Mac\r. Il y a donc plusieurs façons d'écrire une nouvelle ligne. Votre deuxième outil (RegExr) correspond par exemple au simple\r.

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

133
Peter van der Wal

Vous avez différentes fins de lignes 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 convertit toutes les fins de ligne supplémentaires entrées en ce style.

J'ai utilisé Notepad ++ pour coller un échantillon de texte au format Unix et Windows dans Debuggex, et le premier texte collé est le contenu de la session de Debuggex.

Donc, vous devriez laver votre texte dans votre éditeur de texte avant de le coller dans Debuggex. Assurez-vous que vous collez le style souhaité. Debuggex utilise par défaut le style Unix (\ n).

En outre, NEL (\ u0085) est 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, tel que (\r\n|\r|\n), si vous souhaitez également faire correspondre un ancien Mac.

7
Dane

Ceci s'applique uniquement à la question 1.

J'ai une application qui s'exécute sous Windows et qui utilise une boîte d'édition multi-lignes MFC.
La boîte d'édition s'attend à des sauts de ligne CRLF, mais je dois analyser le texte concerné
avec des regex vraiment gros/méchants. 

Je ne voulais pas être stressant à ce sujet tout en écrivant la regex, donc
J'ai fini par normaliser les va-et-vient entre l'analyseur et l'éditeur afin que
les regex utilisent simplement \n. J'intercepte é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" );
 }
1
sln

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()
0
Keelung