encontrar números entre parênteses e arredondá-los

4

Digamos que eu tenha um arquivo chamado tables.tex (muitas tabelas formatadas para tex, incluindo um preâmbulo) com linhas como esta:

some words (xyz, abc) & 0.00071 (0.07846) & 0.00411 (-0.13542) \
some more words (1) & 0.00341 (-0.59991) & 0.00001 (0.99453) \

Preciso encontrar todos os números entre parênteses que não são anteriores ao primeiro '&' em uma linha que termina com uma barra invertida dupla e substitua-as por uma versão arredondada, arredondada para 3 dígitos. Então, minha saída nas duas linhas acima ficaria assim:

some words (xyz, abc) & 0.00071 (0.078) & 0.00411 (-0.135) \
some more words (1) & 0.00341 (-0.600) & 0.00001 (0.995) \

Qual é a maneira mais eficiente de fazer isso? Eu encontrei respostas neste site que descrevem como fazer certas partes desta operação de várias maneiras (números redondos, números de impressão entre parênteses, awk, perl, etc), mas estou tendo problemas para colocar tudo junto em bom estado trabalho).

    
por molly 29.03.2014 / 22:11

2 respostas

3

Awk ou Perl seriam boas ferramentas para esse trabalho. O Perl é mais fácil graças à sua construção para aplicar código arbitrário a uma correspondência de expressão regular.

perl -pe '
    if (s/^([^&]*&)//) {             # if there's a &, then strip the prefix…
        print $1;                    # and print it
        s[\((-?[0-9]*\.[0-9]+)\)]    # replace decimal numbers in parentheses…
         [sprintf("(%.3f)",$&)]eg    # …by their rounding
    }
'
    
por 30.03.2014 / 01:41
1
. 4<<HERE /dev/fd/4
    echo "$(sed -rn '/\\/{:l;s/([^&]*&.*\()([-0-9.]*)(\).*)/\
        "$(printf "%.3f" "" )"/;tl;p;}'<<\SED
    some words (xyz, abc) & 0.00071 (0.07846) & 0.00411 (-0.13542) \
    some more words (1) & 0.00341 (-0.59991) & 0.00001 (0.99453) \ 
    SED
    )"
HERE

OUTPUT:

some words (xyz, abc) & 0.00071 (0.078) & 0.00411 (-0.135) \
some more words (1) & 0.00341 (-0.600) & 0.00001 (0.995) \

Aparentemente, isso é muito semelhante à resposta do @Gilles - que eu estou apenas começando a perceber - em que ambos usamos printf para obter o arredondamento feito. Eu acho que é provavelmente um dado nesse caso, já que é o que acontece. É claro que isso usa apenas construções de shell e sed para realizar o mesmo objetivo, mas se as ferramentas que ele recomenda estiverem disponíveis para você, elas provavelmente serão mais rápidas.

Há uma exceção notável à similaridade em nossa lógica aqui. Isso usa um teste de ramificação - e, portanto, requer que o GNU sed - recaia sobre a string para encontrar possíveis falhas. Gilles imprime e retira a parte não usada da string antes de pesquisar, o que provavelmente é mais rápido. Se eu tivesse que escolher entre usar os dois, eu iria com o dele. Ainda assim, acredito que esta resposta é suficiente por si só para permanecer.

    
por 30.03.2014 / 13:10