atualiza a linha com base na linha anterior

5

Eu tenho um problema, já que não estou familiarizado com o awk. Eu tenho o arquivo csv gerado a partir da saída sar -d convertida para o estilo csv:

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
,iscsi0,0,0.0,0,0,0.0,0.0
,scsi_vhc,0,0.0,0,0,0.0,0.0
,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
,iscsi0,0,0.0,0,0,0.0,0.0
,scsi_vhc,0,0.0,0,0,0.0,0.0
,nfs1,0,0.0,0,0,0.0,0.0

e eu quero converter para isso

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
12:35:00,iscsi0,0,0.0,0,0,0.0,0.0
12:35:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:35:00,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
12:45:00,iscsi0,0,0.0,0,0,0.0,0.0
12:45:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:45:00,nfs1,0,0.0,0,0,0.0,0.0

Minha tentativa, mas desde awk lê linha por linha, eu não sei manter o valor da linha anterior. Eu esperaria que o que tenho trabalhasse. Qualquer ideia de como posso obter o resultado desejado. Eu tentei com awk, mas eu acho que isso deve ser possível com sed ou da maneira mais difícil com um script de shell personalizado (estou tentando evitar fazer essa parte).

#!/usr/bin/awk -f
BEGIN {
        FS=",";
}
{
        print $1
        if ($1 != "") {
                mydate=$1;
                print $0;
        }
        else {
                print $mydate","$0;
        }
}

Executando o sistema com o Solaris 11.1.

    
por BitsOfNix 29.03.2014 / 09:53

3 respostas

2

Fica um pouco longo quando você parece ter linhas em branco na entrada. O seguinte pode funcionar para você:

awk -F'[, ]' '{if (NF!=0 && $1=="") {$1=prev} prev=$1}1' OFS=, inputfile

A idéia é dividir os campos em , e espaço em branco (o último para manipular a primeira linha de entrada). Verifique se o primeiro campo está em branco e o número de campos não é zero (manipular linhas em branco) e, em seguida, substitua o primeiro campo pelo primeiro campo armazenado anteriormente.

Para sua entrada, produziria:

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
12:35:00,iscsi0,0,0.0,0,0,0.0,0.0
12:35:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:35:00,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
12:45:00,iscsi0,0,0.0,0,0,0.0,0.0
12:45:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:45:00,nfs1,0,0.0,0,0,0.0,0.0
    
por 29.03.2014 / 09:59
1

com sed :

sed '/^[0-9]/{               # if line starts with digit
h                            # overwrite hold buffer with pattern space content
s/\([^,]*\),.*//           # extract timestamp
x                            # exchange: put the original line back into pattern
}                            # space and the timestamp in hold space
/^,/{                        # if line starts with a comma
G                            # append hold space (timestamp) to pattern space
s/\(.*\)\n\(.*\)//       # swap the initial line content and the timestamp 
}' infile

em uma linha:

sed -e'/^[0-9]/{h;s/\([^,]*\),.*//;x' -e\} -e'/^,/{G;s/\(.*\)\n\(.*\)//' -e\} infile
    
por 18.07.2015 / 01:56
1

Outro sed :

sed '$!N;/\n,/s/\([^,]*\).*\n/&/;P;D' <in >out

Para cada linha de entrada que é ! não a $ última, sed anexará a linha de entrada N ext ao espaço padrão, precedido por um caractere \n ewline. Em seguida, ele tentará uma s/// ubstitution que envolve a cópia do primeiro grupo possível de ^, caracteres não-vírgula no espaço imediatamente anterior a uma vírgula que segue imediatamente um \n ewline. Se não pode fazer isso, bem, nenhum dano feito, eu acho.

sed irá então P rint até o primeiro \n ewline no espaço padrão e D elete mesmo antes de iniciar o ciclo novamente a partir do topo com o próximo par de linhas de entrada.

OUTPUT

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
12:35:00,iscsi0,0,0.0,0,0,0.0,0.0
12:35:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:35:00,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
12:45:00,iscsi0,0,0.0,0,0,0.0,0.0
12:45:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:45:00,nfs1,0,0.0,0,0,0.0,0.0
    
por 18.07.2015 / 01:50

Tags