regex pour correspondre à EOF

90

J'ai des données qui ressemblent à ceci

john, dave, chris
rick, sam, bob
joe, milt, paul

J'utilise cette expression régulière pour faire correspondre les noms

/(\w.+?)(\r\n|\n|,)/

qui travaille pour la plupart , mais les extrémités de fichiers brusquement après le dernier mot qui signifie la dernière valeur ne se termine pas \r\n, \nou ,il se termine par EOF. Existe-t-il un moyen de faire correspondre EOF dans regex afin que je puisse le mettre correctement dans ce deuxième groupe?

Ryan
la source
Essayez-vous de capturer tous les noms dans un groupe ou un groupe de capture par nom?
Andrew Hare
une chose à faire en cas de problème avec les regex est d'essayer des éléments de votre modèle de manière isolée. si vous êtes préoccupé par le jeton à la fin, testez votre expression sans lui.
akf
je voulais juste ajouter un excellent site de test de regex: regexplanet.com/simple
northpole
@Sinan - Je suis d'accord; fusionné
Marc Gravell

Réponses:

159

La réponse à cette question \Zm'a pris un certain temps à comprendre, mais cela fonctionne maintenant. Notez qu'à l'inverse, \Acorrespond au début de la chaîne entière (par opposition au début d'une ligne ^et $correspond au début d'une ligne).

Ryan
la source
5
Juste un avertissement si vous recherchez une telle fonctionnalité dans netbeans pour une recherche de fichiers de projet par opposition à une recherche dans un fichier , ce qui suit se comportera différemment ... (\s*)\?>(\s*)\Z... et après quelques recherches supplémentaires, voici ce qui fonctionnerait sur un dossier de projet : (\s*)\?>(\s*)(\n*)(\W)\Z FYI: il s'agit de remplacer toutes les balises php de fermeture par des sauts de ligne à la fin du fichier.
MediaVince
1
Il s'avère que cela \Afonctionne également dans Visual Studio find and replace. Comme toujours, utilisez de telles choses avec prudence, mais cela m'a évité une tonne de problèmes manuels une fois que j'étais heureux de faire la bonne chose.
Steve Pettifer
Pendant que j'utilise la Scannerclasse de Java pour lire un fichier entier à la fois; si j'utilise \Zcomme délimiteur, le caractère de nouvelle ligne de fin est coupé. Lorsque j'ai changé le délimiteur en \z, le caractère de nouvelle ligne de fin est conservé. Il semble que la réponse de Martin Dorey s'applique également à Java.
mmdemirbas
24

EOF n'est pas réellement un personnage. Si vous avez une chaîne multiligne, alors «$» correspondra à la fin de la chaîne ainsi qu'à la fin d'une ligne.

En Perl et ses frères, \Aet \Zcorrespond au début et à la fin de la chaîne, en ignorant totalement les sauts de ligne.

Les extensions GNU aux expressions régulières POSIX utilisent \`et \'pour les mêmes choses.

paxdiablo
la source
17

Dans Visual Studio, vous pouvez trouver EOF comme ceci: $(?![\r\n]). Cela fonctionne que vos fins de ligne soient CR, CRLF ou simplement LF.

En prime, vous pouvez vous assurer que tous vos fichiers de code ont un marqueur de nouvelle ligne final comme ceci:

               Find What: (?<![\r\n])$(?![\r\n])
            Replace With: \r\n
 Use Regular Expressions: checked
Look at these file types: *.cs, *.cshtml, *.js

Comment ça marche:

Trouvez toute fin de ligne (une correspondance de largeur nulle) qui n'est pas précédée de CR ou LF et qui n'est pas non plus suivie de CR ou LF. Une réflexion vous montrera pourquoi cela fonctionne!

Notez que vous devez remplacer par le caractère de fin de ligne souhaité, que ce soit CR, LF ou CRLF.

ErikE
la source
Il existe un bogue dans Visual Studio 2019 où effectuer un remplacement tout avec cela peut entraîner l'ajout de deux nouvelles lignes à la fin du fichier. Je pense que cela a quelque chose à voir avec l'option de nouvelle ligne d'insertion automatique lors de l'enregistrement.
Stevoisiak
9

Comparez le comportement du \ Z suggéré par Ryan avec \ z:

$ perl -we 'my $ corpus = "bonjour \ n"; $ corpus = ~ s / \ Z / monde / g; print (": $ corpus: \ n") '
:Bonjour le monde
monde:
$ perl -we 'my $ corpus = "bonjour \ n"; $ corpus = ~ s / \ z / monde / g; print (": $ corpus: \ n") '
:Bonjour
monde:
$ 

perlre sez:

\ Z Correspond uniquement à la fin de la chaîne, ou avant la nouvelle ligne à la fin
\ z Correspond uniquement à la fin de la chaîne

Une traduction du cas de test en Ruby (1.8.7, 1.9.2) se comporte de la même manière.

Martin Dorey
la source
2

Devez-vous vraiment capturer les séparateurs de ligne? Sinon, cette regex devrait être tout ce dont vous avez besoin:

/\w+/

Cela suppose que toutes les sous-chaînes que vous souhaitez mettre en correspondance sont entièrement constituées de caractères de mots, comme dans votre exemple.

Alan Moore
la source
2

Peut-être essayer $ (EOL / EOF) au lieu de (\ r \ n | \ n)?

/\"(.+?)\".+?(\w.+?)$/
Marc Gravell
la source
2

Récemment, je cherchais quelque chose comme ça, mais pour JavaScript.

Mettre ceci ici, afin que toute personne ayant le même problème puisse en bénéficier

var matchEndOfInput = /$(?![\r\n])/gm;

Fondamentalement, cela correspondrait à la fin de la ligne, qui n'est pas suivie d'un retour chariot ou de caractères de nouvelle ligne. En gros, c'est la même chose que \Zpour JavaScript.

Zlatin Zlatev
la source
1

En supposant que vous utilisiez le bon modificateur forçant à traiter la chaîne comme un tout (pas ligne par ligne - et si \ n fonctionne pour vous, vous l'utilisez), ajoutez simplement une autre alternative - fin de chaîne: (\ r \ n | \ n |, | $)

noeud feuille
la source
0

/(\w.+?)(\r\n|\n|,|$)/

cube
la source
5
Probablement. Je ne me souviens plus :-)
cube