Tengo una lista de archivos y números de línea correspondientes donde quiero realizar la sustitución:
s/LOG.error/LOG.warn
Hay otros lugares donde esto podría ocurrir y no queremos alterar esas líneas. ¿Cómo puedo hacer esto usando find y sed?
El archivo tiene el formato:
FooBar.java 125
FooBar.java 180
FooBar2.java 128
Esto es lo que encontré mientras buscaba una manera de hacer esto:
cat filenames.txt | xargs sed -i '<get-line-number-here>s/LOG.error/LOG.warn' <get-file-name-here>
Respuesta1
Deberá dividir el archivo en particiones por archivo de destino y realizar operaciones sed -i
en cada archivo individualmente. Suponiendo que tiene los nombres de archivo y los números de línea agrupados por nombre de archivo y en orden ascendente, puede hacer algo como
awk '$1 != prev { if (prev) print "\047 " prev;
prev=$1;
printf "sed -i \047" }
{ print $2 "s/LOG\\.error/LOG.warn/" }
END { if (prev) print "\047 " prev }' filenames.txt | sh
Este es un truco rápido y sucio que se romperá de maneras interesantes y posiblemente peligrosas si los nombres de los archivos en la primera columna no son un solo token.
Básicamente, refactorizamos su archivo de texto en una secuencia de sed
scripts. Entonces tu ejemplo se convertirá en
sed -i '125s/LOG\.error/LOG.warn
180s/LOG\.error/LOG.warn/
' FooBar.java
sed -i '128s/LOG\.error/LOG.warn/
' FooBar2.java
Lo que notará es un sh
script que contiene un sed
script para cada archivo.
Si está en una plataforma *BSD (incluido Mac OS), deberá cambiar sed -i
cuál sed -i ''
sería en Awk "sed -i \047\047"
para poder incrustar correctamente las comillas simples sin alterar las comillas del shell circundante (para que toda la línea se convierta en printf "sed -i \047\047 \047" }
(sic)).