Substituindo uma linha em vários arquivos

Substituindo uma linha em vários arquivos

Tenho uma lista de arquivos e números de linha correspondentes onde desejo realizar a substituição:

s/LOG.error/LOG.warn

Existem outros lugares onde isso pode ocorrer e não quero perturbar essas linhas. Como posso fazer isso usando find e sed?

O arquivo está formatado como:

FooBar.java 125
FooBar.java 180
FooBar2.java 128

Isto é o que descobri enquanto procurava uma maneira de fazer isso:

cat filenames.txt | xargs sed -i '<get-line-number-here>s/LOG.error/LOG.warn' <get-file-name-here>

Responder1

Você precisará dividir o arquivo em partições por arquivo de destino e executar sed -icada arquivo individualmente. Supondo que você tenha os nomes dos arquivos e números de linha agrupados por nome de arquivo e em ordem crescente, você pode fazer 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 é um hack rápido e sujo que irá quebrar de maneiras interessantes e possivelmente perigosas se os nomes dos arquivos na primeira coluna não forem um único token.

Basicamente, refatoramos seu arquivo de texto em uma sequência de sedscripts. Então seu exemplo será transformado em

sed -i '125s/LOG\.error/LOG.warn
180s/LOG\.error/LOG.warn/
' FooBar.java
sed -i '128s/LOG\.error/LOG.warn/
' FooBar2.java

que você notará é um shscript que contém um sedscript para cada arquivo.

Se você estiver em uma plataforma *BSD (incluindo Mac OS), você precisará alterar sed -io sed -i ''que seria no Awk "sed -i \047\047"para incorporar corretamente aspas simples sem perturbar as aspas do shell ao redor (para que a linha inteira se torne printf "sed -i \047\047 \047" }(sic)).

informação relacionada