Я использую оболочку Bash для обработки некоторых файлов журнала, которые я должен вставить файл CSV. Информацией, в которой я нуждаюсь, является дата начала процесса и время, дата окончания процесса и время, идентификатор Процесса и сообщение
Что я сделал, grep строки включая запущенный процесс и поместил их в файл, затем Grep закончил процессы и поместил их во второй файл. После того, как сделанный, я беру каждый файл и использую awk, чтобы разделить и извлечь необходимую информацию, вот мир кода, который я использую,
input=starts.txt
while IFS= read -r line
do
procs=`echo $line | awk '{ print $6;}'
date_s=`echo $line | awk '{ print $1;}'`
time_s=`echo $line | awk '{ print $2;}'`
m1=`echo $line | awk '{ print $3;}'`
m2=`echo $line | awk '{ print $4;}'`
m3=`echo $line | awk '{ print $5;}'`
m4=`echo $line | awk '{ print $7;}'`
m5=`echo $line | awk '{ print $8;}'`
m6=`echo $line | awk '{ print $9;}'`
echo $procs ";" $date_s ";" $time_s ";" $m1 $m2 $m3 $m4 $m5 $m6
one < "$input" > result.csv
Строки имеют следующий формат:
02/01/2018 10:32:35 ANR4930I Reclamation process 1320 started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
У меня есть две проблемы теперь:
Я считал Вашу задачу как "перемещение поле 5 (process number
) к передней стороне и затем выводу первые 3 поля, разделенные ;
, сопровождаемый ;
и затем остаток.
В Perl я сделал бы это как так (как острота):
perl -a -n -l -e \
'unshift @F, splice(@F, 5, 1);
print join(";", @F[0..2]), ";@F[3..$#F]";' \
< input.txt > output.csv
Результат:
input.txt
:
02/01/2018 10:32:35 ANR4930I Reclamation process 1320 started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
02/01/2018 10:32:35 ANR4930I Reclamation process 4567 started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
output.csv
:
1320;02/01/2018;10:32:35;ANR4930I Reclamation process started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
4567;02/01/2018;10:32:35;ANR4930I Reclamation process started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
perl -a -n -l -e
@F
\n
) также как выходной разделитель (вполне упрощенный)unshift @F, splice(@F, 5, 1);
@F
(который содержит одну строку Вашего входного разделения файла в пробеле), и предварительно ожидает тот 5-й элемент перед массивом @F
.print join(";", @F[0..2]), ";@F[3..$#F]";'
@F
с ;
промежуток, затем;
и затем остальная часть массива @F
запуск в 3-м элементе в конец с пространством как разделитель. (print "@any_array"
печатает объекты, разделенные пространством.)Если Вы хотите тот же код как сценарий (сказать format-messages.pl
), затем это выглядит немного отличающимся, потому что переключатели командной строки к Perl (которые теперь отсутствуют) implicitely добавляют некоторый код, который теперь должен быть добавлен explicitely. (Да, существуют другие пути, но...),
#!/usr/bin/env perl
use strict;
use warnings;
while(<>) {
my @F = split;
unshift @F, splice(@F, 5, 1);
print join(";", @F[0..2]), ";@F[3..$#F]\n";
}
Сделайте a chmod +x format-messages.pl
и затем запущенный этот скрипт с ./format-messages.pl < input.txt > output.csv
Самым большим улучшением будет полное отсутствие цикла оболочки и обработка каждой записи (строки) непосредственно в Awk. Например:
$ awk '{
printf("%s;%s;%s;", $6, $1, $2)
for(i=3; i<NF;i++) {
if(i==6) continue;
printf("%s ", $i)
}
printf("%s\n",$NF)
}' input
1320;02/01/2018;10:32:35;ANR4930I Reclamation process started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)