Pruebe la búsqueda sed recursiva y reemplácela antes de ejecutarla

13

¿Hay alguna forma de ejecutar una búsqueda recursiva de prueba y reemplazar usando sed, antes de ejecutarla? Solo quiero imprimir los resultados antes de hacer la búsqueda y reemplazar. Algo así como hacer eco de los resultados de,

grep -rl term1 . |xargs sed -i -e 's/term1/term2/'
usuario251482
fuente
Haga una copia de los datos, ejecute su comando, inspeccione el resultado.
Kusalananda

Respuestas:

10

Puede ejecutar sedsin -iy pasar por la salida conless

grep -rl --null term1 . | xargs -0 sed -e 's/term1/term2/' | less

Luego, ejecute sedcon -i.bakpara crear copias de seguridad que puede diferir después

grep -rl --null term1 . | xargs -0 sed -i.bak -e 's/term1/term2/'
diff somefile.bak somefile
# verify changes were correct

Editar: como se sugiere en el comentario, use grep --null | xargs -0. Esto hace que los nombres de archivo sean terminados por el byte nulo, lo que lo hace seguro para nombres de archivo con caracteres inusuales como nueva línea. Sí, \nes un carácter válido en un nombre de archivo unix. Los únicos caracteres prohibidos son la barra /y el carácter nulo.\0

grebneke
fuente
Interesante, traté de encontrar el significado de -i pero no estaba en la lista bajo man sed. Tu solución funcionó. ¿Cuál sería la mejor manera en su opinión de simplemente enumerar las líneas, no todo el archivo? En lugar de canalizar en menos, canalicé | grep term2, que funcionó, pero también obtuve algunos resultados con caracteres extraños.
user251482
@ user251482 - "¿Solo enumerar las líneas", como en "ver una diferencia entre el archivo antiguo y el nuevo"?
grebneke
1
@StephaneChazelas Sí, o incluso mejor, grep -rl --nullya que OP no especificó OS y -Zsignifica algo diferente en BSD / OSX (descomprimir). --nulles lo mismo en GNU y BSD
grebneke 05 de
1
@grebneke. Buen punto, pero tenga en cuenta que el OP está utilizando la sintaxis sed de GNU, por lo que podemos suponer que no está en BSD. Tenga en cuenta que grepes (una bifurcación de) el grep de GNU en FreeBSD y NetBSD. En NetBSD, -Ztodavía significa --null(según la página de manual), pero estoy de acuerdo: nulo es más portátil. También tenga en cuenta que ni --null ni -Z trabajan en OpenBSD
Stéphane Chazelas
1
@grebneke, está sed -i '' -e s/.../en BSD sed(no hay opciones opcionales allí)
Stéphane Chazelas
5

Usar sedcon en findlugar degrep

En primer lugar, emplearía en findlugar de grep, y esto por tres buenas razones:

  1. findpermite una selección de archivos más precisa. Por ejemplo, solo grep -r string *.txtgenerará archivos en el directorio actual; no aquellos en subdirectorios.
  2. findviene con la poderosa -execopción que elimina la necesidad de toda la --null … |xargs 0construcción.
  3. Las opciones -readabley -writablede findevitarán perder tiempo en archivos a los que no se puede acceder.

Prueba de captura

Dicho esto, grepse presta para una primera prueba para ver qué se capturaría:

$ find . -exec grep term1 {} \;

o más específicamente:

$ find . -type f -name '*.txt' -readable -writable -exec grep term1 {} \;

Carrera en seco

Ahora, proceda con una sedcarrera en seco. La sedopción -nes sinónimo de --quiety pal final de la sedexpresión imprimirá el espacio de patrón actual.

$ find . -exec sed -n 's/term1/term2/gp' {} \;

o más específicamente:

$ find . -type f -name '*.txt' -readable -writable -exec sed -n 's/term1/term2/gp' {} \;

Ejecución

Si todo se ve bien, emita el comando definitivo reemplazando la sedopción -npor -i"en su lugar" y quitando el pal final.

$ find . -exec sed -i 's/term1/term2/g' {} \;

o más específicamente:

$ find . -type f -name '*.txt' -readable -writable -exec sed -i 's/term1/term2/g' {} \;

Más findejemplos

Más findejemplos se pueden encontrar aquí .

Serge Stroobandt
fuente