Esto es lo que obtengo de la documentación: \zs
"comienza la parte resaltada" después de hacer coincidir la expresión regular anterior, y \@<=
"comienza la parte resaltada" después de hacer coincidir el átomo anterior . Pero no entiendo exactamente las sutilezas de esto, entonces, ¿alguien puede explicar cómo difieren un poco más en profundidad?
Esto es lo que me hizo sentir curiosidad: si corro
/\_s\zsnnoremap
es decir, seleccione nnoremap
precedido por un espacio o un inicio de línea (es decir, la nueva línea desde la línea anterior, de ahí la \_
anterior s
) y luego ejecute gn
para ingresar al Modo Visual y seleccione visualmente la siguiente coincidencia, por alguna razón solo la primera columna (es decir la primera n
en nnoremap
) se selecciona - a pesar del hecho de que toda la nnoremap
palabra se destacó con el :hlsearch
encendido.
Sin embargo, si en su lugar ejecuto la búsqueda
/\_s\@<=nnoremap
e intente gn
, todo nnoremap
está correctamente seleccionado. ¿Qué podría estar pasando aquí? ¿Descubrí (me atrevo a decir) algún error oscuro?
fuente
:h patterns
pero mi memoria sugiere que las expresiones regulares están compuestas de átomos, si eso ayuda a explicar la diferencia.Respuestas:
Parece que de hecho has encontrado un error oscuro. He implementado el objeto de
gn
texto en 2012 para Vim 7.3 algo. Básicamente funciona de la siguiente manera:1) Busca hacia atrás la última coincidencia de la expresión regular actual.
2) Busca la próxima coincidencia de la expresión regular actual.
Esto debería dejar en claro que el cursor estará en el inicio de la próxima partida, incluso si ya estaba allí al comienzo de 1).
Finalmente3) busca el final de la expresión regular actual. y pone el cursor allí.Ahora, lo que sucede aquí es que la búsqueda del final de la coincidencia actual se ajusta y regresa al final de la coincidencia anterior (porque
wrapscan
ya está establecida, después de estar deshabilitada para 1)). Luego establece el marcador Visual en el área desde el inicio (final del punto 2) y el área movida por el siguiente elemento de búsqueda 3).Analizaré más de cerca el problema y probablemente enviaré un parche para Vim más tarde.
[Actualización 22.05.2018] He escrito y enviado un parche para corregir este comportamiento.
[Actualización2 22.05.2018] Y el parche se ha fusionado como parche nivel 8.1.0018
[Actualización 22.10.2019] A partir del parche Vim 8.1.629, el tercer paso ya no se realiza. En cambio, Vim ahora puede determinar el final de la partida al encontrar el comienzo de la partida (Paso 2)
fuente
Christian ha abordado por completo la cuestión del comportamiento defectuoso de
gn
, pero todavía hay diferencias fundamentales entre\zs
y\@<=
. El ser más grande\@<=
modifica un átomo precedente, mientras que\zs
es un átomo en sí mismo.Considerar:
Regex 1 coincide, ya que
\%1c
coincide con la columna 1 y hay una X allí.\zs
simplemente hace que el partido se reinicie en una posición después de la X.Sin embargo, Regex 2 no coincide, porque aunque
\%1c
coincide con la primera columna,X\@<=
tiene un ancho cero (como se menciona en la documentación) ynnoremap
comienza en la columna 2. No hay nada que compense la diferencia de posición entre las columnas 1 y 2.Regex 3 coincide desde que
nnoremap
comienza en la columna 2.fuente
nnoremap
de la expresión regular produciría una coincidencia; pero la expresión regular todavía falla incluso sin ella. Creo que falla porque\%1cX\@<=
expresa una posición que no puede existir.\%1c
coincide con la posición en la columna 1, yX\@<=
pide un personajeX
que coincida antes de eso. Pero no puede haber ningún personaje antes de la primera columna. Es por eso que, incluso si lo reemplazaX
con un punto (cualquier carácter), la expresión regular\%1c.\@<=
aún falla.\zs
se aplica a toda la expresión regular y establece que el siguiente carácter sea el primer carácter de toda la coincidencia. Cualquier cosa anterior al\zs
no se incluirá como parte del texto correspondiente.\@<=
, por otro lado, solo afecta a los átomos directamente a su alrededor, lo que le permite especificar que el siguiente átomo solo coincidirá si sigue al átomo anterior. Entonces, por ejemplo, la expresión regular:Emparejará todo el texto entre dos instancias de
bar
(incluidas las instancias mismas), pero solo si la segunda está precedida porfoo
. es decir, coincidirá con:pero no:
Debido a que
\@<=
está localizado de esta manera, incluso puede usar\@<=
varias veces en una sola expresión:Lo siguiente coincidirá con tres instancias de
bar
, pero solo si las dos últimas están precedidas por cada unafoo
.es decir, dado el texto:
Solo coincidirá con la primera línea.
fuente
\zs
, es decir, esto también debería funcionar:\vfoo\zsbar.*(foo)@<=bar
.\zs
no se puede sustituir en absoluto.\zs
y\ze
puede ser reemplazado por mirar alrededor de los patrones de expresiones regulares, y son más potentes, ¿verdad? Porque son más potentes porque se pueden usar más de una vez y se pueden agrupar\(\)
. Y también porque funcionan como la mirada de Perl alrededor de la expresión regular. Algo equivocado?\zs
/\ze
cuando pueda, porque son más rápidos que las miradas.\zs
y\ze
obviamente son más intuitivos. Gracias por las explicaciones