2011-06-28 19 views
6

Buscar y reemplazar archivos múltiples es difícil en mi editor. Hay muchos trucos que se pueden hacer con find, xargs y sed/awk incluyendo búsqueda y reemplazo en varios archivos. Pero de alguna manera no pude encontrar una manera de hacer esto interactivo. ¿Conoces una manera de hacer eso?Búsqueda interactiva y reemplazo del shell

+1

¿Qué quiere decir con interactiva? Del editor? – Noam

+0

¿O te refieres interactivo de la línea de comando? – Straff

Respuesta

1

Simplemente use Vim.

Comience por usar find para hacer una lista de todos los archivos que necesitan cambios de ese modo.

vim `find . -name '*.c' -exec grep junk {} \;` 

que se inicia vim con todos los .c archivos que contienen la cadena junk. Ahora, en vim hacer su cambio en el primer archivo:

:%s/junk/rubbish/g 

Y a continuación, escriba :wIntroduzca:nIntroduzca para el siguiente archivo.

Ahora necesita repetir el proceso de edición. Si solo hay un comando sustituto y solo unos pocos archivos, escriba :ArribaIngrese para repetir el comando de sustitución.

Pero si hay muchas, debe usar map para crear un par de macros de kestroke. La primera macro haría los comandos sustitutos y la segunda macro haría los comandos w y n para guardar los cambios y obtener el siguiente archivo.

He usado esto (y versiones anteriores con vi) durante los últimos 30 años. En particular, cuando codificas las dos partes de esto como dos macros de pulsación de teclas, puedes ejecutarlo muy rápido porque es fácil mantener presionada la tecla de control, y escribir un par de letras, por ejemplo, RY, una y otra vez. Es más rápido que el tiempo que se tarda en escribir un script totalmente automático y, como esto es fácil de reproducir, puede hacerlo en cualquier máquina en la que esté trabajando.

3

me gustaría añadir estas modificaciones a la respuesta de Dillon:

La opción -le debe añadirse al comando grep.

vim `find . -name '*.c' -exec grep -le '\<junk\>' {} \;` 

entonces usted está en Vim, pero que no tienen la oportunidad de elegir con qué reemplazar, añadir c opción al final de reemplazos interactivos y bufdo al principio para caminar a través de cada archivo:

:bufdo %s/junk/rubbish/gce 

Más tarde guardar todo su trabajo:

:bufdo wq! 
5

principio KISS:

vim 
:args `ls` 
:argdo %s#SEARCH#REPLACE#gec |update 

Primer carácter afer% s se utiliza como separador

0

Aquí es una mejora de la respuesta de @ jhvaras si encuentra que con frecuencia quiere hacer esto, o si sólo desea buscar archivos bajo control de versiones.

function SvnProjectSubstitute(replacement) 
    execute "args `grep -sl '" . @/ . "' $(svn --recursive list)`; echo -n ''" 
    argdo execute "substitute//" . a:replacement . "/gc" 
endfunction 

command -nargs=1 -complete=file Gsubstitute call SvnProjectSubstitute(<f-args>) 

Notas:

  • Como ya he formulado aquí, que sólo busca los archivos que Subversion tiene bajo control de versiones desde el directorio actual de manera recursiva hacia abajo. Por supuesto, puede generalizarlo o adaptarlo a un sistema de gestión de versiones diferente de acuerdo con sus necesidades.
  • El patrón que se utiliza es el último patrón que se buscó. Una vez más, si no te gusta esto, puedes ajustarlo a tus necesidades.
  • Gsubstitute es para "sustituto global". Puedes llamar al comando como quieras pero me gusta porque :Gs parece ajustarse estilísticamente a Vim.
  • Esta es una buena solución si tiene una gran cantidad de archivos, porque le quita la carga a Vim para buscarlos a todos (es decir, también podría resolver this guy's problem).
  • El eco de "no hacer nada" al final y el -s pasado a grep son para cubrir un error que encuentra grep. grep proporciona un código de retorno distinto de cero incluso si encuentra buenos resultados.

Ejemplo de uso:

/OldClassName 
:Gs NewClassName 

Una razón me gusta usar el patrón de búsqueda anterior se que le permite dar rápidamente una clase de un nombre completamente diferente al colocar el cursor en la clase, haciendo una * o #, y luego su comando :Gs, que le ahorra tener que escribir toda la cadena de búsqueda.

0

puede probar esta herramienta para buscar y reemplazar en modo intercative una carcasa interior

https://sourceforge.net/projects/isartool/

no necesita un servidor X, y si quieres que es recursivo en el directorio utilizando la opción -r.

Ciao

0

no pude conseguir la respuesta de Mario al trabajo, pero si uso xargs funciona.

Además, la mayoría de las veces que quiero buscar y reemplazar en varios archivos, quiero cambiar una identificación alfanumérica de una cosa a otra, como cambiar el nombre de una variable o una clase, etc. Para eso, es muy útil para agregar una búsqueda hacia atrás negativo y búsqueda negativa hacia delante para no permitir caracteres de palabra antes o después de lo que va a reemplazar, y por esa grep necesita el indicador P de usar Perl expresiones regulares:

vim `find . -name '*.cpp' -o -name '*.hpp' | xargs grep -Ple '(?<!\w)FIND(?!\w)'` 

:bufdo %s/FIND/REPLACE/gce 

por supuesto, es útil para terminar con esto en un script para que no tenga que volver a escribirlo cada vez. Aquí hay un principio:

#!/bin/bash 

if [[ $# < 2 ]]; then 
    echo "Usage: search-replace <search> <replace>" 
    exit 1 
fi 

search="$1" 
replace="$2" 

files=`find . -name '*.cpp' -o -name '*.hpp' | xargs grep -Ple "(?<!\w)$search(?!\w)"` 

if [[ -z "$files" ]]; then 
    echo "No matching .cpp or .hpp files." 
    exit 1 
fi 

# The stuff surrounding $search is the negative lookahead/lookbehind 
vim -c "set hidden | bufdo %s/\(\w\)\@<!$search\(\w\)\@!/$replace/gce" $files 

Algo que todavía no funciona con gracia para mí con una solución de Mario es que al final del primer archivo que dice:

Error detected while processing command line: 
E37: No write since last change (add ! to override) 

Esto evita que la búsqueda y reemplazo fluya hacia el siguiente archivo. Parece que "establecer oculto" corrige esto, y lo he usado en mi script anterior.

Un problema restante es que después de buscar y reemplazar en el primer archivo, parece procesar el primer archivo por segunda vez, deshaciendo las sustituciones iniciales. Si alguien sabe por qué está sucediendo eso, házmelo saber.

manera
1

Una UNIX para hacer esto con grep, xargs, y vi/vim:

  1. Crear un alias

Esto ayudará a evitar los comandos largos cuando se desea excluir ciertas cosas de grep .

alias ge='grep --exclude=tags --exclude=TAGS --exclude-dir=.git --exclude-dir=build --exclude-dir=Build --exclude-dir=classes --exclude-dir=target--exclude-dir=Libraries --exclude=*.log --exclude=*~ --exclude=*.min.js -rOInE $*' 
  1. realizar la búsqueda y comprobar su lista de archivos

Comando:

ge -l 'foo' . 
  1. Realice el buscar de nuevo, diciéndole a vim que reemplace interactivamente en cada archivo

Comando:

ge -l 'foo' . | xargs -L 1 -o vim -c '%s/foo/bar/gc' 

Explicación del comando:

  • La parte hasta que la tubería es el comando de búsqueda repite

  • Después de la tubería, que llamamos xargs para lanzar vim en cada archivo

  • "-L 1" le dice a xargs que ejecute el comando en cada línea en lugar de combinar todas las líneas en un solo comando. Si prefiere ejecutar vim en todos los archivos a la vez, elimine "-L 1" de xargs.

  • "-o" dice xargs utilizar el terminal real en lugar de/dev/null

Usted tiene dos opciones para este comando:

a) vim lanzamiento en todos los archivos a la vez

Ventajas:

  • comando es fácil cancelar: acaba de salir de vim

Desventajas:

  • debe de cambiar a cada búfer de vuelta y volver a ejecutar el comando "% s" en él

  • Si usted tiene una gran cantidad de archivos, esto puede hacer vim consumen una gran cantidad de memoria (a veces tanto como un IDE en toda regla!)

b) Lanzamiento vim a su vez para cada archivo

Ventajas:

  • todo está automatizado. Vim se pone en marcha y lleva a cabo el comando de búsqueda

  • Luz en la memoria

Desventajas:

  • Es difícil para cancelar: dejar de fumar vim se acaba de hacer xargs abren la siguiente

Prefiero la variante b) ya que es automática y más parecida a UNIX. Con una planificación cuidadosa, primero inspeccionando la lista de archivos, y tal vez ejecutando el comando en los subdirectorios para reducir el alcance, es muy agradable de usar.

ventajas generales:

  • Se puede lograr con las herramientas estándar de UNIX, disponible en prácticamente cualquier plataforma

  • Es agradable de usar

desventajas generales:

  • Tienes que escribir la expresión de búsqueda dos veces

  • que puede pegarle a problemas con la fiesta de escapar de búsqueda compleja/reemplazar expresiones

Cuestiones relacionadas