actualizar línea basada en la línea anterior

actualizar línea basada en la línea anterior

Tengo un problema porque no estoy familiarizado con awk. Tengo un archivo csv generado a partir de la salida sar -d convertido al 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

y quiero convertir a esto

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

Mi intento, pero como awk lee línea por línea, no sé cómo mantener el valor de la línea anterior. Esperaría que lo que tengo funcione. ¿Alguna idea de cómo puedo obtener el resultado deseado? Lo intenté con awk, pero supongo que esto debería ser posible con sed o de la manera más difícil con un script de shell personalizado (estoy tratando de evitar hacer esta parte).

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

Ejecutando el sistema con Solaris 11.1.

Respuesta1

Se vuelve un poco largo porque parece que tienes líneas en blanco en la entrada. Lo siguiente podría funcionar para usted:

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

La idea es dividir los campos en ,espacios en blanco (este último para manejar la primera línea de entrada). Compruebe si el primer campo está en blancoyel número de campos no es cero (maneja líneas en blanco), luego reemplaza el primer campo con el primer campo previamente almacenado.

Para su aporte, produciría:

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

Respuesta2

Con 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

en una línea:

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

Respuesta3

Otro sed:

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

Para cada línea de entrada que !no sea la $última, sedse agregará la Nlínea de entrada externa al espacio del patrón precedida por un \ncarácter de línea nueva. Luego intentará una s///sustitución que implica copiar el primer grupo posible de ^,caracteres que no sean comas en el espacio que precede a una coma que sigue inmediatamente a una \nlínea ew. Si no puede hacerlo, supongo que no habrá ningún daño.

sedLuego Pimprimirá hasta la primera \nlínea ew en el espacio del patrón y Dla eliminará antes de comenzar el ciclo nuevamente desde la parte superior con el siguiente par de líneas de entrada.

PRODUCCIÓN

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

información relacionada