atualizar linha com base na linha anterior

atualizar linha com base na linha anterior

Estou com um problema porque não estou familiarizado com o awk. Eu tenho um 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 como o awk lê linha por linha, não sei como manter o valor da linha anterior. Eu esperaria que o que tenho funcionasse. Alguma ideia de como posso obter o resultado desejado. Eu tentei com o awk, mas acho que isso deveria ser possível com sed ou da maneira mais difícil com um script de shell personalizado (estou tentando evitar fazer esta parte).

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

Executando o sistema com Solaris 11.1.

Responder1

Fica um pouco longo porque parece que há 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 ideia é dividir os campos em ,espaços em branco (este último para lidar com a primeira linha de entrada). Verifique se o primeiro campo está em brancoeo número de campos não for zero (lidar com linhas em branco) e, em seguida, substituir o primeiro campo pelo primeiro campo armazenado anteriormente.

Para sua opinião, 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

Responder2

Com sed:

sed '/^[0-9]/{               # if line starts with digit
h                            # overwrite hold buffer with pattern space content
s/\([^,]*\),.*/\1/           # 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\(.*\)/\2\1/       # swap the initial line content and the timestamp 
}' infile

em uma linha:

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

Responder3

Outro sed:

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

Para cada linha de entrada que !não seja a $última, sedanexará a Nlinha de entrada ext ao espaço padrão precedido por um \ncaractere ewline. Em seguida, ele tentará uma s///substituição que envolve copiar o primeiro grupo possível de ^,caracteres sem vírgula para o espaço imediatamente anterior a uma vírgula que segue imediatamente um \newline. Se não puder fazer isso, bem, nenhum dano causado, eu acho.

sedirá então Pimprimir até a primeira \nlinha ew no espaço padrão e Deletá-la antes de iniciar o ciclo novamente a partir do topo com o próximo par de linhas de entrada.

SAÍDA

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

informação relacionada