Duplicando automaticamente o valor dos números em uma string em vários arquivos

3

Estou tentando modificar o código-fonte Java em vários arquivos .java que contêm sequências semelhantes a esta:

private static final Height biomeHeight = new Height(0.1F, 0.2F);

Existem mais de 75 e gostaria de encontrar uma maneira de automatizar a duplicação dos valores de 0,1F e 0,2F em várias strings. Note que os valores de 0.1F e 0.2F são diferentes em cada arquivo.

Por exemplo, em um arquivo, a string pode ser esta:

private static final Height biomeHeight = new Height(0.2F, 0.1F);

Nesse caso, eu gostaria que fosse:

private static final Height biomeHeight = new Height(0.4F, 0.2F);

Como posso automatizar isso?

    
por A.J. Ruckman 08.05.2015 / 14:20

2 respostas

1

Você pode considerar o uso de perl , por exemplo,

perl -pe 's/(?<=Height\()([0-9.]+)F(.+?)([0-9.]+)F(?=\);)/sprintf "%sF%s%sF",2*$1,$2,2*$3/e' file.java

As (?<=Height\() e (?=\);) são afirmações de tamanho zero ou lookarounds que limitam as correspondências à região específica entre esses delimitadores, após o que os valores numéricos são extraídos usando grupos de captura valores $1 ... $3 podem então ser manipulados na expressão de substituição usando sprintf com o modificador /e (evaluate).

Para aplicar recursivamente, você pode usar o comando find , por exemplo,

find . -name '*.java' -execdir perl -i'.bak' -pe 's/(?<=Height\()([0-9.]+)F(.+?)([0-9.]+)F(?=\);)/sprintf "%sF%s%sF",2*$1,$2,2*$3/e' {} \;

Executando em seu arquivo de teste:

$ perl -i'.bak' -pe 's/(?<=Height\()([0-9.]+)F(.+?)([0-9.]+)F(?=\);)/sprintf "%sF%s%sF",2*$1,$2,2*$3/e' bop.txt

usando então diff para confirmar a substituição

$ diff bop.txt.bak bop.txt
12c12
<   private static final Height biomeHeight = new Height(8.0F, 0.025F);
---
>   private static final Height biomeHeight = new Height(16F, 0.05F);
    
por steeldriver 08.05.2015 / 15:28
3

Eu suponho que todas as linhas que você deseja alterar iniciem com a string private static final Height biomeHeight = new Height . Se sim, então você pode usar awk :

awk -F'[(,)]' '$1=="private static final Height biomeHeight = new Height"\
{$0=$1"("$2*2"F, "$3*2"F);";}1' file

Explicação:

  • -F'[(,)]' sets awk 's delimitador para os caracteres ( , ) e , que temos os parâmetros dessa função java nos campos awk $ 2 e $3
  • $1=="..." se o primeiro campo for igual à string
    • {$0=$1"("$2*2"F, "$3*2"F);";} reformata a nova string com os valores duplicados.
  • 1 , esse único 1 no final equivale a {print $0} , portanto, imprima a linha inteira (editada ou não editada).

Editar:

A declaração awk acima só funciona quando a linha começa exatamente com private static ... . Quando há espaços, precisamos mudar um pouco:

awk -F'[(,)]' '$1~/[ ]*private static final Height biomeHeight = new Height/\
{$0=$1"("$2*2"F, "$3*2"F);";}1'

Eu verifiquei com seu código colado . Veja o diff :

$ diff file_old file_new
12c12
<       private static final Height biomeHeight = new Height(8.0F, 0.025F);
---
>       private static final Height biomeHeight = new Height(16F, 0.05F);
    
por chaos 08.05.2015 / 14:54