¿Mostrar solo líneas coincidentes?

31

En un archivo largo, me gustaría buscar un patrón que coincida con aproximadamente 200 líneas más o menos. Las líneas coincidentes están en lugares aleatorios en el archivo.
Cuando una línea coincide, solo la línea en sí es relevante, sin contexto arriba o abajo.

Normalmente, buscaría /y saltaría a través de los partidos con n.
Pero eso significa que solo hay una o dos líneas relevantes en la pantalla a la vez.

¿Hay alguna manera de ocultar todas las líneas que no coinciden, mientras revisa la lista de líneas de resultados?


Un enfoque de fuerza bruta sería eliminar todas las líneas que no coinciden, y deshacer esa eliminación más tarde. Pero eso es feo de varias maneras, incluso si no terminara en un deshacer persistente ...

Volker Siegel
fuente

Respuestas:

34
:vimgrep pattern %
:cwin

vimgrepbuscará su patrón en el archivo actual ( %), o en cualquier archivo que especifique.

cwinluego abrirá un búfer en su ventana que solo mostrará las líneas deseadas. Puede usar prácticamente cualquier comando de navegación / búsqueda dentro del cwinbúfer. Presione regresar para saltar a la línea debajo del cursor en el archivo fuente.

Zach Ingbretsen
fuente
1
:vimgrepse puede abreviar a:vim
D. Ben Knoble
¿Cómo vuelvo al búfer de nuevo?
pasha
¿también cómo cierro el búfer? gracias de antemano
pasha
Desde el búfer quickfix (cwindow) puede presionar retorno en cualquier línea para saltar a esa ubicación en el búfer original. Puede cerrar el búfer cwindow desde cualquier lugar :ccl[ose]o, sin embargo, normalmente cierra un búfer (por ejemplo, cambie a él y :bd). Puede volver a abrir el búfer de corrección rápida ejecutando :cw[indow]nuevamente, y usará sus últimos resultados de vimgrep.
Zach Ingbretsen
15

Puede enumerar todas las líneas coincidentes con

:g/{pattern}

(El :printcomando se puede omitir; es el valor predeterminado para :g).

Ingo Karkat
fuente
1
Este es el "grep original" ( g/REgexp/p) ... El problema es que no puedes saltar fácilmente a uno de los partidos, aunque ...
Martin Tournoij
@Carpetsmoker: Tienes razón; para eso, tengo un complemento, mira mi otra respuesta.
Ingo Karkat
Eso podría ser útil para muchos casos. ¿Se puede redirigir la salida a un nuevo búfer? Eso permitiría tener resaltado de sintaxis en las líneas. (Hmm ... eso plantea otra pregunta, espera un segundo ...)
Volker Siegel
@IngoKarkat cuál es el significado de g. Supongo que es un patrón global. Por lo general, hago búsquedas de VI con una barra inclinada /patterny esto encontraría todos los sucesos. Uno puede navegar hacia ellos presionando la letran
Alexander Cska
@AlexanderCska: No, no es un modificador de búsqueda, sino un comando separado :g[lobal]que toma un patrón como argumento. Encontrará todos los detalles en :help :global.
Ingo Karkat
12

Puede usar las opciones foldmethody foldexprpara plegar las líneas irrelevantes.

Después de buscar, la última búsqueda se almacena en el @/registro. Por lo tanto, puede plegar fácilmente todo lo que no coincida de esta manera (solo para coincidencias de una línea):

:setlocal foldexpr=getline(v:lnum)=~@/?0:1 foldmethod=expr

Se pueden encontrar métodos más avanzados, como agregar múltiples niveles de plegado para líneas de contexto que puede mostrar u ocultar, o hacer coincidir varias líneas, en el Wiki de Vim Tips .

Ben
fuente
Parece que hay un set foldlevel=0necesario? Pero tal vez eso es lo predeterminado.
Volker Siegel
1
Sí, el valor predeterminado es cero, pero si no funciona sin él, agregarlo no puede doler. :-)
Ben
Pero ahora ... ¿cómo cambiarlo de nuevo, sin rastros?
Volker Siegel
en modo normal, puede usar 'zi' para alternar entre plegado y encendido.
John O'M.
La mayoría de las veces, cuando hago esto, primero :tab spobtengo una nueva vista desechable en el archivo. Luego, regresar es tan simple como :closecualquier otra forma de eliminar la pestaña.
Ben
6

Si el orden no importa, simplemente mueve las líneas.

:g/pat/m0

Para más ayuda ver:

:h :g
:h :m
Peter Rincker
fuente
1
Y :g/pat/m$(mover las líneas coincidentes hasta el final) también está bien,
Lerner Zhang
6

[d] elija todas las líneas, no (!) patrones coincidentes:

:g!/pattern/d

o incluso más simple (gracias por los comentarios de 'B Layer'):

:v/pattern/d
Kevin Liu
fuente
Sí, pero es más convencional usar el equivalente en :vlugar de :g!. (¡No recuerdo la última vez que vi el último usado, TBH!)
Capa B
2

Si desea enumerar todas las líneas coincidentes (como en mi otra respuesta), y luego saltar a una coincidencia particular, mi complemento FindOccurrence proporciona una [/asignación para eso (y [npara el último patrón de búsqueda, en lugar de buscar una). [/patternenumera como :g/pattern, pero luego pide el número del partido al que saltar.

Ingo Karkat
fuente
0

Otra forma es usar :h :ilist, lo uso para obtener una visión general de la página de manual. su resultado se ve así:

~/find.~
  1:    3 NAME
  2:    6 SYNOPSIS
  3:    9 DESCRIPTION
  4:   18 OPTIONS
  5:   93 EXPRESSION
  6:  779 EXAMPLES
  7:  877 HISTORY
  8:  931 BUGS

Aquí hay una pequeña función que le permite elegir ir a la línea de resultados por índice:

function! s:select_ilist(ilist_result)
  if empty(a:ilist_result) || a:ilist_result =~# '^\_s*Error'
    return
  endif

  let select = input(a:ilist_result . "\ngoto : ")
  if empty(select) | return | endif

  " ilist result starts with '\nfilename\n', filename can be empty
  let lines = split(a:ilist_result[stridx(a:ilist_result, "\n", 1) : ], "\n")
  if select <= 0 || select > len(lines) | return | endif

  exec matchstr(lines[select-1], '^\v\s*\d+\:\s+\zs\d+')
endfunction

Se puede usar así:

command! -buffer Section call s:select_ilist(execute('silent! ilist /\v\C^[A-Z][^a-z]+$/'))
dedowsdi
fuente