Я пытаюсь переформатировать файл журнала, чтобы дата и время появлялись в начале строки. Мои журналы выглядят так:
blah, blah, blah, Friday, Mar 13,2015 16:59:42
yadi, yadi, yada, Friday, Mar 13,2015 16:51:11
Я бы хотел, чтобы они выглядели так:
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada
Я зашел так далеко, что нашел правильный шаблон grep с grep -o -i -e '[a-zA-Z]*, [a-z][a-z][a-z] [0-9]*,[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]' ~/log.txt
.
Как я могу переместить эти результаты шаблона слева от информационной строки? Спасибо за вашу помощь.
Попробовать sed
со следующим regex:
$ sed -i.bak 's_\(.*\),[[:blank:]]\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)_\2 \1_' file.txt
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada
Здесь мы использовали sed
'метод замены S Group для получения желаемого вывода.
\(.*\)
будет соответствовать до blah, blah, blah
поскольку мы имеем ,[[:blank:]]
соответствовать ,
после него.\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)
будет соответствовать остающейся части строки (часть, которую мы хотим поместить в запуск).Затем мы имеем \2 \1
помещать вторую группу сначала и затем затем пространство и затем первую группу.
Исходный файл будет сохранен как file.txt.bak
, если Вы не хотите то использование просто -i
вместо -i.bak
.
** Хотя Вы получите желаемый вывод, использование Regex/sed не будет оптимальным решением в этом случае.
Править: Если у Вас есть строка как [Internet disconnected] Friday, Mar 13,2015 15:48:34
, попробуйте это:
$ sed -i.bak 's_\(.*[^,]\),*[[:blank:]]\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)_\2 \1_' file.txt
Friday, Mar 13,2015 15:48:34 [Internet disconnected]
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada
В предыдущем regex мы имели \(.*\),[[:blank:]]
(запятая и пробел после первой группы соответствия), теперь для включения новой строки в вывод мы сделали первую группу соответствия \(.*[^,]\)
чтобы гарантировать, что это не заканчивается запятой и затем мы соответствовали ,*
т.е. одна или несколько запятых. Так, новое sed
команда будет работать на все упомянутые случаи.
с awk это - намного более простой синтаксис
awk -F, '{print $4","$5","$6","$1","$2","$3}' file.txt
Золотое правило регулярных выражений, "меньше больше". Необходимо всегда пытаться записать самый простой regex, который соответствует данным. Это не только делает намного легче читать и понять, это также намного более устойчиво и не порвет с небольшими изменениями в формате. Так, в Вашем случае Вы могли просто сделать:
$ sed -r 's/(.*), ([^,]+,[^,]+,[^,]*$)/\2\1/' file
Friday, Mar 13,2015 16:59:42blah, blah, blah,
Friday, Mar 13,2015 16:51:11yadi, yadi, yada,
, Который соответствует всему с начала строки до запятой и пространства ((.*),
) и, потому что шаблон окружается круглыми скобками, сохраняет его как \1
. Теперь, потому что вторая полученная группа (второй шаблон в круглых скобках) поднимается до конца строки (это - то, что $
средства), мы знаем, что соответствуем правильной части в первой.
вторые взгляды для фрагмента одного или нескольких несимволов запятой ([^,]+
), запятая, другой набор незапятых, другой запятой и затем как можно большего количества несимволов запятой до конца строки. Тем путем мы можем правильно идентифицировать последние поля как дату. Эти s///
оператор замены, который здесь просто переключает порядок 1-го и 2-го полученного шаблона.
Вы могли также сделать то же самое в awk
. По-видимому, текст перед датой является переменным, таким образом, мы не можем принять то же количество полей для каждой строки. Поэтому мы должны будем считать в обратном направлении поля от конца строки:
$ awk -F, '{
printf "%s,%s,%s, ", $(NF-2),$(NF-1),$NF;
for(i=1;i<NF-3;i++){printf "%s,", $i} print $(NF-3)
}' file
Friday, Mar 13,2015 16:59:42, blah, blah, blah
Friday, Mar 13,2015 16:51:11, yadi, yadi, yada
Или в Perl:
$ perl -lpe 's/(.*), ([^,]+,[^,]+,[^,]*$)/\2, \1/' file
Friday, Mar 13,2015 16:59:42, blah, blah, blah
Friday, Mar 13,2015 16:51:11, yadi, yadi, yada
$ perl -F, -lane 'print join ",",@F[$#F-2,$#F-1,$#F,0..$#F-3]' file
Friday, Mar 13,2015 16:59:42,blah, blah, blah
Friday, Mar 13,2015 16:51:11,yadi, yadi, yada