Puede hacer algo crudo con un pequeño script de Perl que recibe instrucciones de realizar reemplazos línea por línea ( -l -pe
) en los archivos pasados como argumentos ( -i
):
perl -i -l -pe '
if (/from/) { # is the source text present on this line?
printf STDERR ("%s: %s [y/N]? ", $ARGV, $_); # display a prompt
$r=<STDIN>; # read user response
if ($r =~ /^[Yy]/) { # if user entered Y:
s/from/to/g; # replace all occurences on this line
}' /path/to/files
Las posibles mejoras serían colorear partes de la solicitud y apoyar cosas como "reemplazar todas las ocurrencias en el archivo actual". Solicitar por separado cada aparición en una línea sería más difícil.
Segunda parte, haciendo coincidir los archivos. Si no hay demasiados archivos involucrados y está ejecutando zsh, puede hacer coincidir todos los archivos en el directorio actual y sus subdirectorios de forma recursiva:
perl -i -l -pe '…' **/*(.)
Si su shell es bash ≥4, puede ejecutar perl … **/*
, pero eso producirá mensajes de error espurios porque sed intentará (y fallará) ejecutar en directorios. Si solo desea realizar el reemplazo en un conjunto de archivos como archivos C, puede restringir las coincidencias (que funciona en bash ≥4 o zsh):
perl -i -l -pe '…' **/*.[hc]
Si necesita un control más preciso sobre qué archivos está reemplazando, o su shell no tiene la construcción de coincidencia de directorio recursiva **
, o si tiene demasiados archivos y obtiene un error de "línea de comando demasiado larga", use find
. Por ejemplo, para realizar un reemplazo en todos los archivos nombrados *.h
o *.c
en el directorio actual y sus subdirectorios (en sistemas más antiguos, es posible que deba usar en \;
lugar de +
al final de la línea (el +
formulario es más rápido pero no está disponible en todas partes).
find . -type f -name '*.[hc]' -exec perl -i -l -pe '…' {} +
Dicho esto, me quedaría con un editor interactivo si necesita interacción. Gert ha mostrado una forma de hacerlo en Vim , aunque requiere abrir todos los archivos que desea buscar, lo que puede ser un problema si hay muchos.
En Emacs, así es como puedes hacer esto:
- Reúna los nombres de archivo con
M-x find-name-dired
(especifique un directorio de nivel superior) o M-x find-dired
(especifique una find
línea de comando arbitraria ).
- En el búfer dired resultante , presione
t
para marcar todos los archivos, luego Q
( dired-do-query-replace-regexp
) para realizar un reemplazo con una solicitud en los archivos marcados.
s/from/to/g
con un error de formato después, en lugar de hacers/from/to/gc
hincapié en loc
que había intentado escribir (no puede hacerlo con Markdown, puede hacerlo con<code>
y<strong>
etiquetas HTML).