Переместить шаблон в начало строки

Я пытаюсь переформатировать файл журнала, чтобы дата и время появлялись в начале строки. Мои журналы выглядят так:

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.

Как я могу переместить эти результаты шаблона слева от информационной строки? Спасибо за вашу помощь.

5
задан 22 March 2015 в 15:32

3 ответа

Попробовать 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 команда будет работать на все упомянутые случаи.

5
ответ дан 22 March 2015 в 15:32

с awk это - намного более простой синтаксис

awk -F, '{print $4","$5","$6","$1","$2","$3}' file.txt
4
ответ дан 22 March 2015 в 15:32

Золотое правило регулярных выражений, "меньше больше". Необходимо всегда пытаться записать самый простой 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
3
ответ дан 22 March 2015 в 15:32

Другие вопросы по тегам:

Похожие вопросы: