regex para que coincida con EOF

90

Tengo algunos datos que se ven así

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

Estoy usando esta expresión regular para que coincida con los nombres

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

que funciona en su mayor parte, pero el archivo termina abruptamente después de la última palabra, lo que significa que el último valor no termina en \r\n, \no ,termina con EOF. ¿Hay alguna manera de hacer coincidir EOF en expresiones regulares para que pueda ponerlo correctamente en esa segunda agrupación?

Ryan
fuente
¿Está intentando capturar todos los nombres en un grupo o un grupo de captura por nombre?
Andrew Hare
Una cosa que debe hacer cuando tiene problemas con las expresiones regulares es probar elementos de su patrón de forma aislada. si le preocupa el token al final, pruebe su expresión sin él.
akf
solo quería agregar un excelente sitio de prueba de expresiones regulares
northpole
@Sinan - estoy de acuerdo; fusionado
Marc Gravell

Respuestas:

160

La respuesta a esta pregunta \Zme tomó un tiempo darme cuenta, pero ahora funciona. Tenga en cuenta que por el contrario, \Alos partidos a partir de toda la cadena (en oposición a ^, y $que coincide con el comienzo de una línea).

Ryan
fuente
5
Solo un aviso si está buscando tal funcionalidad en netbeans para una búsqueda de archivos de proyecto en lugar de una búsqueda de archivos , lo siguiente se comportará de manera diferente ... (\s*)\?>(\s*)\Z... y después de investigar un poco más, esto es lo que funcionaría en una carpeta de proyecto : (\s*)\?>(\s*)(\n*)(\W)\Z FYI: esto es para reemplazar todas las etiquetas php de cierre por saltos de línea al final del archivo.
MediaVince
1
Resulta que \Atambién funciona en Visual Studio buscar y reemplazar. Como siempre, use esas cosas con precaución, pero me ahorró un montón de líos manuales una vez que estaba feliz de que realmente haría lo correcto.
Steve Pettifer
Mientras estoy usando la Scannerclase de Java para leer un archivo completo a la vez; si lo uso \Zcomo delimitador, se recortó el carácter de nueva línea final. Cuando cambié el delimitador a \z, se conservó el carácter de nueva línea final. Parece que la respuesta de Martin Dorey también se aplica a Java.
mmdemirbas
24

EOF no es en realidad un personaje. Si tiene una cadena de varias líneas, entonces '$' coincidirá con el final de la cadena y con el final de una línea.

En Perl y sus hermanos, \Ay \Zempareja el principio y el final de la cadena, ignorando por completo los saltos de línea.

Las extensiones GNU para expresiones regulares POSIX usan \`y \'para las mismas cosas.

paxdiablo
fuente
17

En Visual Studio, puede encontrar EOF este modo: $(?![\r\n]). Esto funciona si sus finales de línea son CR, CRLF o simplemente LF.

Como beneficio adicional, puede asegurarse de que todos sus archivos de código tengan un marcador de nueva línea final como este:

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

Como funciona esto:

Busque cualquier final de línea (una coincidencia de ancho cero) que no esté precedido por CR o LF, y que tampoco esté seguido por CR o LF. ¡Un poco de pensamiento le mostrará por qué funciona esto!

Tenga en cuenta que debe Reemplazar con el carácter de final de línea deseado, ya sea CR, LF o CRLF.

ErikE
fuente
Hay un error en Visual Studio 2019 en el que reemplazar todo con esto puede dar como resultado que se agreguen dos líneas nuevas al final del archivo. Creo que tiene algo que ver con la nueva línea de inserción automática en la opción de guardar.
Stevoisiak
9

Contraste el comportamiento de \ Z sugerido por Ryan con \ z:

$ perl -we 'mi $ corpus = "hola \ n"; $ corpus = ~ s / \ Z / world / g; print (": $ corpus: \ n") '
:Hola Mundo
mundo:
$ perl -we 'mi $ corpus = "hola \ n"; $ corpus = ~ s / \ z / world / g; print (": $ corpus: \ n") '
:Hola
mundo:
PS 

perlre sez:

\ Z Coincide solo al final de la cadena, o antes de la nueva línea al final
\ z Coincidir solo al final de la cadena

Una traducción del caso de prueba a Ruby (1.8.7, 1.9.2) se comporta de la misma manera.

Martin Dorey
fuente
2

¿Realmente tienes que capturar los separadores de línea? Si no, esta expresión regular debería ser todo lo que necesita:

/\w+/

Eso es asumiendo que todas las subcadenas que desea hacer coincidir consisten completamente en caracteres de palabra, como en su ejemplo.

Alan Moore
fuente
2

¿Quizás probar $ (EOL / EOF) en lugar de (\ r \ n | \ n)?

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

Recientemente estaba buscando algo como esto, pero para JavaScript.

Poner esto aquí, para que cualquier persona con el mismo problema pueda beneficiarse

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

Básicamente, esto coincidiría con el final de la línea, que no va seguido de un retorno de carro o de caracteres de nueva línea. En esencia, esto es lo mismo que \Zpero para JavaScript.

Zlatin Zlatev
fuente
1

Suponiendo que está utilizando el forzado de modificador adecuado para tratar la cadena como un todo (no línea por línea, y si \ n funciona para usted, lo está usando), simplemente agregue otra alternativa: final de cadena: (\ r \ n | \ n |, | $)

nodo de hoja
fuente
0

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

cubo
fuente
5
Probablemente. Ya no recuerdo :-)
cube