totais cumulativos com coluna deslocada

3

Desculpas antecipadas, pois tenho certeza de que esse é um problema fácil. No entanto, aqui vai.

cat blah.txt
aa+2
bb+4
cc+10
dd+31

Eu gostaria de processar blah.txt para produzir o seguinte:

aa+0
bb+2
cc+6
dd+16

A ideia aqui é que a primeira coluna pode ser uma lista de músicas e a segunda é a hora de início.

Meu palpite foi fazer isso usando o awk. Pensei em dois arrays com índices numéricos armazenando $ 1 e o total em execução de $ 2. Minha ideia era mudar o índice numérico para os totais em execução em 1.

tail -r blah.txt | 
awk -F "+" '{ for(i=0;i<=NR;i++) arr[i+1]+=$2; farr[i]=$1 } END 
{ for(i=NR+1;i>1;i--) {if (i==NR) {print farr[NR] FS 0 } 
else { print farr[i] FS arr[i]}}}'

Isso não é conciso, e o que é mais não funciona. Estou confuso com o fracasso da matriz fazendo acima de tudo.

"De qualquer forma", disse nuf, poderia alguém gentil por favor me tirar da minha miséria?

Tom

    
por Tom 14.04.2013 / 11:40

2 respostas

5

Aqui você vai:

$ awk -F+ '{sum+=$2;printf("%s+%d\n",$1,sum-$2);}' blah.txt
aa+0
bb+2
cc+6
dd+16

Edit1: aqui é uma maneira um pouco mais simples, graças ao Sukminder

$ awk -F+ '{printf("%s+%d\n",$1,sum);sum+=$2}' blah.txt

Edit2: E um pouco mais conciso, graças a Bernhard:

$ awk -F+ '{print $1,sum;sum+=$2}' OFS="+" blah.txt

Edit3: mas o primeiro não exibe 0 na primeira linha, então aqui está uma versão corrigida e um pouco compacta que mostra a maneira mais curta de responder à pergunta de Tom (até que algum novo comentário sugira um melhor):

$ awk -F+ '{print$1,s+0;s+=$2}' OFS=+ blah.txt
    
por 14.04.2013 / 11:49
0

A melhor maneira de fazer isso é aprender e usar expressões regulares, pois no futuro isso vai lhe poupar muita dificuldade em fazer esse tipo de coisa.

cat blah.txt | gawk 'match($0, /([^0-9]*)([0-9]+)/, ary) {print ary[1] ary[2]-2}'

Você terá que substituir os últimos 2 pela sua variável de turno. Você deve observar o uso de gawk . Até onde sei, awk regular não pode extrair grupos de expressões regulares.

O que isso faz? Ele faz uma correspondência em $0 , colocando os resultados em ary , usando a expressão regular /([^0-9]*)([0-9]+)/ , que corresponde a: ([^0-9]*) - 0 ou mais caracteres que não são números e o coloca no primeiro índice de array (parênteses são responsáveis para essa coisa chamada agrupamento), então ([0-9]+) corresponde ao número de comprimento diferente de zero (e o coloca como segundo elemento da matriz).

É claro que isso pode ser mais elaborado, juntamente com verificação de erros, casos especiais de correspondência etc. - mas eu encorajo você a explorar isso (ou seja, expressões regulares) por conta própria.

    
por 14.04.2013 / 11:57

Tags