Elimina todo, excepto la compatibilidad con expresiones regulares en Vim

Mi caso específico es un documento de texto que contiene un montón de texto y direcciones IPv4. Quiero eliminar todo excepto las direcciones IP.

Puedo usar :vglobal para buscar ([0-9]{1,3}\.){3}[0-9]{1,3} y eliminar todas las líneas sin direcciones IP, pero después de eso solo sé cómo para buscar toda la línea y seleccionar el texto correspondiente. Hay una manera mas facil.

En resumen, estoy buscando una forma de hacer lo siguiente sin usar un progtwig externo (como grep):

 grep --extended-regexp --only-matching --regexp="([0-9]{1,3}\.){3}[0-9]{1,3}" 

Llamar a grep desde vim puede requerir adaptar mi expresión regular (por ejemplo, eliminar \ v). Usar la búsqueda incremental de vim me muestra que tengo el patrón correcto, y no quiero verificar mi expresión regular en grep también.


Editar: Gracias a Peter, aquí está la función que ahora uso. (C es el registro que, por lo general, critico en mis funciones).

 "" Remove all text except what matches the current search result "" The opposite of :%s///g (which clears all instances of the current search). function! ClearAllButMatches() let old = @c let @c="" %s//\=setreg('C', submatch(0), 'l')/g %d _ put c 0d _ let @c = old endfunction 

Edit2: hice un comando que acepta rangos (pero el valor predeterminado es el archivo completo).

 "" Remove all text except what matches the current search result. Will put each "" match on its own line. This is the opposite of :%s///g (which clears all "" instances of the current search). function! s:ClearAllButMatches() range let is_whole_file = a:firstline == 1 && a:lastline == line('$') let old_c = @c let @c="" exec a:firstline .','. a:lastline .'sub//\=setreg("C", submatch(0), "l")/g' exec a:firstline .','. a:lastline .'delete _' put! c "" I actually want the above to replace the whole selection with c, but I'll "" settle for removing the blank line that's left when deleting the file "" contents. if is_whole_file $delete _ endif let @c = old_c endfunction command! -range=% ClearAllButMatches ,call s:ClearAllButMatches() 

Este efecto se puede lograr mediante el uso de sustitución sub-replace-special y setreg() linewise

 :let @a="" :%s//\=setreg('A', submatch(0), 'l')/g :%d _ :pu a :0d _ 

o todo en una línea como tal:

 :let @a=""|%s//\=setreg('A', submatch(0), 'l')/g|%d _|pu a|0d _ 

Descripción: Usando una sustitución para agregar cada coincidencia en el registro “a” linewise, luego reemplace todo el buffer con el contenido del registro “a”

Explicación:

  1. let @a="" vaciar el registro “a” que agregaremos a
  2. %s//\=setreg('A', submatch(0), 'l')/g sustituyen globalmente utilizando el último patrón
  3. el \=expr reemplazará el patrón con el contenido de la expresión
  4. submatch(0) obtener toda la cadena de lo que acaba de coincidir
  5. setreg('A', submatch(0), 'l') añaden (nota: el capital “a”) a @a la cadena coincidente, pero linewise
  6. %d _ eliminar cada línea en el registro de agujero negro (aka @_)
  7. pu a poner los contenidos de @a en el buffer
  8. 0d _ eliminar la primera línea

Preocupaciones:

  • Esto arruinará uno de tus registros. Este ejemplo fue destruido @a
  • Utiliza el último patrón de búsqueda. Aunque puede modificar el comando sustituto con el patrón que desee: %s//\=setreg('A', submatch(0), 'l')/g

Para más ayuda

 :h :s\= :h :let-@ :h submatch() :h setreg() :h :d :h :p 

Suponiendo que es su expresión regular para que coincida con una dirección IP, supongo que podría hacer algo como:

 :%s/.\{-}\(\).*/\1/g 

donde \1 es el primer grupo coincidente (la dirección sola) y .\{-} utilizado para la concordancia no codiciosa.

 :set nowrapscan :let @a="" gg0qac/\v(\d{1,3}\.){3}\d{1,3}//e+1@aq@adG 

Explicación:

  1. set nowrapscan desactiva la capacidad de buscar «más allá del final del archivo».
  2. let @a="" : vacía el registro a.
  3. gg0 : vaya a la primera columna (0) de la primera línea (gg).
  4. qa : comienza a escribir macros.
  5. c/{pattern} : cambia hasta el patrón.
  6. c{motion} : reemplaza texto con nueva línea (aquí {motion} es /{pat} ).
  7. //e+1 : busca el último patrón, ve un personaje más allá de su final (se ajusta alrededor de una nueva línea, pero si tus líneas se ven así: IPIP , puede haber problemas).
  8. @a : ejecuta @a macros (está vacío cuando lo estás grabando, pero cuando hayas terminado repetirá los pasos 1 a 7 hasta que aparezca un error).
  9. q : finaliza la grabación @a .
  10. @a : ejecuta @a macros.
  11. dG : eliminar al final del archivo.

En resumen, estoy buscando una manera de hacer esto sin dejar vim

Suficientemente fácil:

 :1,$! grep --extended-regexp --only-matching --regexp="([0-9]{1,3}\.){3}[0-9]{1,3}" 

(Aunque en realidad voté la respuesta de sustitución de icecrime)