
Peço desculpas antecipadamente, pois tenho certeza de que este é um problema fácil. No entanto, aqui vai.
cat blah.txt
aa+2
bb+4
cc+10
dd+31
Gostaria de processar blah.txt para produzir o seguinte:
aa+0
bb+2
cc+6
dd+16
A noção aqui é que a primeira coluna pode ser uma lista de músicas e a segunda os horários de início.
Meu palpite era fazer isso usando o awk. Pensei em dois arrays com índices numéricos armazenando $1 e o total acumulado de $2. Minha ideia era mudar o índice numérico dos totais acumulados 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, além do mais, não funciona. Estou confuso com o fracasso da criação do array acima de tudo.
De qualquer forma, 'nuf disse, alguma pessoa gentil poderia, por favor, acabar com meu sofrimento?
Tom
Responder1
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 está 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 tanto compactada que mostra o caminho mais curto para responder à pergunta de Tom (até que algum novo comentário sugira um melhor):
$ awk -F+ '{print$1,s+0;s+=$2}' OFS=+ blah.txt
Responder2
A melhor maneira de fazer isso é aprender e usar expressões regulares, pois no futuro você economizará muitos problemas ao 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 2 últimos pela sua variável shift. Você deve observar o uso de gawk
. Até onde eu sei, regular awk
não pode extrair grupos de expressões regulares.
O que isso faz? Ele faz uma correspondência $0
, colocando os resultados em ary
, usando uma expressão regular /([^0-9]*)([0-9]+)/
, que corresponde a: ([^0-9]*)
- 0 ou mais caracteres que não são números e os coloca no primeiro índice da matriz (os parênteses são responsáveis por aquela coisa chamada agrupamento) e, em seguida, ([0-9]+)
corresponde ao número de comprimento diferente de zero (e coloca-o como segundo elemento do array).
É claro que isso pode ser mais elaborado, juntamente com alguma 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.