Exclua todas as linhas que começam com Log.d

1

Eu tenho um aplicativo para Android e tenho um monte de Log.d(.....); tipo de mensagens que eu simplesmente gostaria de remover.

Eu só quero um comando que remova todos eles (deve passar por todos os diretórios de forma recursiva)

Um desafio, no entanto, é que alguns comandos Log.d vão para a próxima linha, e alguns são assim:

Log.d("I can be easily deleted", "");

Outros são assim

Log.d("I span a new line, "hel" 
+ "lo");

Também não é necessário que o espaçamento seja o mesmo, um Log.d seria 30 caracteres a partir do início da linha, o outro poderia ser 14, etc.

Acho que algo que poderia ser útil é que todos começam com Log.d e terminam com );

Isso deve ser executado em todos os arquivos .java (* .java)

Qual é o comando para fazer isso? Obrigado

    
por K Split X 02.12.2017 / 16:35

1 resposta

2

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' : substitua foo por bar , 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 com Log.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
    
por 03.12.2017 / 00:08