Script básico
Eu usei o perl porque é mais simples de combinar em várias linhas (diferente, digamos, do sed). O script básico é o seguinte.
perl -0777 -pe 's/^Log\.d\(.*?(\n.*?)*?\);\n//gm' input
Explicação
-
perl -0777 -pe
: invoque o perl usando-0777
para fazer o slurp do arquivo inteiro, ou seja, permitindo o processamento de várias linhas. -
's/foo/bar/gm'
: substituafoo
porbar
, mesmo se houver várias correspondências (g
); esta é uma expressão de múltiplas linhas (m
). -
^Log\.d\(.*?(\n.*?)*?\);\n
: procure por linhas que começam comLog.d(
; essa expressão precisa ser escapada (^Log\.d\(
). Pode haver mais caracteres após isso (.*?
), possivelmente uma nova linha com mais caracteres ((\n.*?)
) e, possivelmente, várias iterações dessa última expressão (*?
). Depois disso, procure por um fechamento);
seguido por uma nova linha (com escape de\);\n
). Todos esses curingas são não-vorazes (*?
não*
). Assim, eles tentarão corresponder ao número mínimo de caracteres possíveis, em vez de excluir do primeiro^Log\.d\(
ao final\);\n
do arquivo inteiro.
Teste
input.txt
:
Keep me A
Log.d("I can be easily deleted", "");
Keep me B
Keep me C
Log.d("I span a new line, "hel"
+ "lo");
Keep me D
Executar script:
$ perl -0777 -pe 's/^Log\.d\(.*?(\n.*?)*?\);\n//gm' input.txt
Keep me A
Keep me B
Keep me C
Keep me D
Iterar vários arquivos
Após testar o script como acima, aplique-o em vários arquivos. Use a opção "no local" do perl ( -i
) para modificar os arquivos originais. Faça um backup do diretório primeiro. Se os arquivos estiverem todos diretamente no mesmo diretório, você pode simplesmente enviar vários argumentos para o script usando curingas do shell.
perl -i -0777 -pe 's/^Log\.d\(.*?(\n.*?)*?\);\n//gm' *.java
No entanto, dado que você pode ter diretórios aninhados (e eu não sei qual shell você está usando), você pode usar find
aqui.
find /path/to/dir -name '*.java' -execdir perl -i -0777 -pe 's/^Log\.d\(.*?(\n.*?)*?\);\n//gm' {} \;
Explicação
-
find /path/to/dir
: procure em/path/to/dir
. -
-name '*.java'
: localize apenas arquivos correspondentes a essa expressão. -
-execdir perl -i -0777 -pe 's/^Log\.d\(.*?(\n.*?)*?\);\n//gm' {} \;
: execute o script acima no local (-i
) no arquivo correspondente{}
.
Veja man find
para mais informações sobre este formato.
benchmarking da versão sed
Como don_crissti sugere no comentários , há um comando sed que também fará isso.
sed -e '/Log/{' -e ': do' -e '/);/d;N' -e 'b do' -e '}' input.txt
Eu testei os dois comandos usando o seguinte arquivo como entrada.
Keep me A
Log.d("I can be easily deleted", "");
Keep me B
Keep me C
Log.d("I span a new line, "hel"
+ "lo");
Keep me D
Log.d("I span a new line, "hel"
+ "lo" +
+ "there");
Keep me E
Eu fiz alguns benchmarking comparando comandos. A versão perl
é um pouco mais rápida para este arquivo no meu sistema.
$ time (for i in {1..1000}; do perl -0777 -pe 's/^Log\.d\(.*?(\n.*?)*?\);\n//gm' input.txt > /dev/null; done)
================
CPU 101%
user 1.484
system 3.372
total 4.793
$ time (for i in {1..1000}; do sed -e '/Log/{' -e ': do' -e '/);/d;N' -e 'b do' -e '}' input.txt > /dev/null; done)
================
CPU 101%
user 2.647
system 2.847
total 5.429
Eu também criei outro arquivo de teste com 1000 repetições do input.txt
acima. Neste caso, a versão sed foi mais rápida.
$ time (for i in {1..100}; do perl -0777 -pe 's/^Log\.d\(.*?(\n.*?)*?\);\n//gm' input1000 > /dev/null; done)
================
CPU 100%
user 1.132
system 0.409
total 1.535
$ time (for i in {1..100}; do sed -e '/Log/{' -e ': do' -e '/);/d;N' -e 'b do' -e '}' input1000 > /dev/null; done)
================
CPU 100%
user 0.560
system 0.298
total 0.853