обновить строку на основе предыдущей строки

обновить строку на основе предыдущей строки

У меня проблема, так как я не знаком с awk. У меня есть csv-файл, сгенерированный из вывода sar -d, преобразованного в стиль 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

и я хочу преобразовать в это

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

Моя попытка, но поскольку awk читает построчно, я не знаю, как сохранить предыдущее значение строки. Я бы ожидал, что то, что у меня есть, должно работать. Есть идеи, как мне получить желаемый результат. Я пробовал с awk, но полагаю, что это должно быть возможно с sed или сложным способом с помощью пользовательского скрипта оболочки (я пытаюсь избежать этой части).

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

Запуск системы с Solaris 11.1.

решение1

Это становится немного длинным, так как у вас, кажется, есть пустые строки во входных данных. Следующее может подойти вам:

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

Идея состоит в том, чтобы разделить поля на ,пробелы и (последний для обработки первой строки ввода). Проверьте, является ли первое поле пустымиколичество полей не равно нулю (обрабатывать пустые строки), то замените первое поле ранее сохраненным первым полем.

В ответ на ваш запрос будет выдано следующее:

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

решение2

С 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

в одной строке:

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

решение3

Другой sed:

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

Для каждой строки ввода, которая !не является $последней, sedдобавит Nстроку ввода ext к пространству шаблона, которому предшествует \nсимвол ewline. Затем он попытается выполнить s///замену, которая включает копирование первой возможной группы ^,символов не-запятая в пространство, предшествующее запятой, которая следует сразу за \newline. Если он не может этого сделать, ну, я думаю, ничего страшного.

sedзатем Pвыведет текст до первой \nстроки в пространстве шаблона и Dудалит ее, прежде чем начать цикл заново сверху со следующей парой строк ввода.

ВЫХОД

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

Связанный контент