
У меня проблема, так как я не знаком с 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///
замену, которая включает копирование первой возможной группы ^,
символов не-запятая в пространство, предшествующее запятой, которая следует сразу за \n
ewline. Если он не может этого сделать, ну, я думаю, ничего страшного.
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