Converte uma coluna de épocas em uma coluna de tempo a partir de 0

0

O que eu tenho

Oi, imagine muitos desses arquivos, em que a primeira coluna é a época e a (s) outra (s) coluna (s) são alguns dados:

1000333,34,1
1001456,56,0
1005356,34,2

O que eu preciso

Eu preciso transformá-los nisso:

0,34,1
1123,56,0
5023,34,2

Os números da primeira coluna acima vêm de:

 1000333 - 1000333 =    0
 1001456 - 1000333 = 1123
 1005356 - 1000333 = 5023

Contexto

Esses arquivos estão em várias pastas em uma pasta grande chamada logs_swapoff , eles terminam com _times.csv (há outro csv s nessas pastas que não devem ser tocadas).

Exemplos de arquivos:

logs_swapoff/folder1/modifyMe_times.csv
logs_swapoff/folder1/dontTouchMe_cores.csv
logs_swapoff/folder2/modifyMeToo_times.csv

Estou planejando usar esse loop no bash, mas não sei como fazer a tarefa em si.

for filename in $(find logs_swapoff/* -name '*_times.csv') ; do
    # filename without extension (to write the output with a similar name?)
    fname=$(dirname $filename'"/"'basename -s .csv $filename);

    ?????

done;

Obrigado pessoal:)

    
por onlycparra 11.02.2016 / 00:13

1 resposta

1

Enumerando os arquivos

Analisando a saída de find é frágil . É melhor fazer com que find chame o programa de transformação. Para gerar o nome do arquivo de saída, uma simples expansão de parâmetro é suficiente para mude o sufixo _times.csv para _subtracted.csv (por exemplo).

find logs_swapoff -name '*_times.csv' -exec sh -c '
  <"$1" awk "$0" >"${1%_times.csv}_subtracted.csv"
' '…' {} \;

O '…' é o código awk a ser executado. Eu coloquei fora do trecho de shell para simplificar a citação.

Transformando cada arquivo

Você precisa processar um arquivo linha por linha e em cada linha fazer uma transformação de texto simples envolvendo alguma aritmética. Isso faz do awk uma ferramenta ideal para o trabalho. A única dificuldade com sua saída de amostra é que você parece querer se alinhar à menor largura; isso não pode ser feito sem primeiro ler todo o arquivo para determinar a largura máxima. Se você está satisfeito com alguns espaços extras, você pode processar o arquivo linha por linha.

awk '
    NR==1 {start = $1}
    {n = $1 - start; sub(/^ *[0-9]+/, ""); printf "%6d", n; print}
'

Explicação: na primeira linha, defina a variável start para o primeiro número. Em seguida, em cada linha, subtraia o valor de start do primeiro número e retire o primeiro número. Imprima o resultado da subtração (preenchido com 6 caracteres com espaços) e o restante da linha.

Este código assume que há sempre espaço após o primeiro número. Se este não for o caso, você pode fazer uma correspondência mais precisa.

awk '
    NR==1 {match(/[0-9]+/); start = substr(RSTART, RLENGTH)}
    match(/[0-9]+/) {n = substr(RSTART, RLENGTH) - start; sub(/ *[0-9]+/, ""); printf "%6d", n; print}
'

Se os campos forem separados por vírgulas e não houver espaços com os quais se preocupar, declare a vírgula como um separador de campos. Então você pode simplesmente substituir o primeiro campo por um valor atualizado.

awk -F, '
    NR==1 {start = $1}
    {$1 = $1 - start; print}
'

Então, colocando tudo junto (versão vírgula):

find logs_swapoff -name '*_times.csv' -exec sh -c '
  <"$1" awk -F, "$0" >"${1%_times.csv}_subtracted.csv"
' '
    NR==1 {start = $1}
    {$1 = $1 - start; print}
' {} \;
    
por 11.02.2016 / 01:06