Intereting Posts
Брандмауэр: почему нет маршрута для размещения? Код возврата всегда равен 0 после запуска echo "\ $ macroName" | ftp -i mymachine как заменить значение на это значение + константа Как поставить «rm -i» на итерации? Как создать копию файла в нескольких каталогах? что происходит во время переключения режима мастер-мастерства? Как я могу найти домен сервера samba? Как копировать рекурсивно все файлы не старше 1 дня? Можно ли просмотреть список имен файлов zip-файла, который находится внутри другого zip-файла? Минимальная Linux, застрявшая в здании GRUB Как закрыть выбранное окно с помощью клавиатуры в режиме обзора gnome-shell? Приостановка процесса с помощью -SIGSTOP для достаточно длинных причин. Ядро Oops Stack Overflow hard vs – in limits.conf Вставьте одинарные кавычки в текстовый файл для использования в качестве SQL-запроса, который следует за open-parens, используя sed Ubuntu 12.04: обновление пакета сообщения

Преобразование отформатированных дат в секундах с эпохи

У меня есть файл:

pablo tty8 Thu Nov 1 12:51:21 2012 still logged in (unknown tty8 Thu Nov 1 12:50:57 2012 - Thu Nov 1 12:51:21 2012 (00:00) pablo tty2 Thu Nov 1 12:50:39 2012 still logged in pablo tty7 Thu Nov 1 12:49:45 2012 - Thu Nov 1 12:50:56 2012 (00:01) (unknown tty7 Thu Nov 1 12:34:32 2012 - Thu Nov 1 12:49:45 2012 (00:15) 

Я хочу заменить файл в указанную дату на секунду. Я хочу напечатать:

 pablo tty8 1351770681 still logged in (unknown tty8 1351770657 - 1351770681 (00:00) pablo tty2 1351770639 still logged in pablo tty7 1351770585 - 1351770656 (00:01) (unknown tty7 1351769672 - 1351770585 (00:15) 

Я пробовал эту команду:

 gawk --posix 'function my() {"date -d \047"$0"\047 +%s" | getline b; gsub( /[A-Za-z]{3} [A-Za-z]{3} [0-9] ([0-9]{2}:){2}[0-9]{2} [0-9]{4}/,b );print} { my() }' file 

Вышеуказанная команда не работает:

 $ gawk --posix 'function my() > {"date -d \047"$0"\047 +%s" | getline b; > gsub( /[A-Za-z]{3} [A-Za-z]{3} [0-9] ([0-9]{2}:){2}[0-9]{2} [0-9]{4}/,b ); print} > { my() }' ta date: błędna data: `pablo tty8 Thu Nov 1 12:51:21 2012 still logged in ' pablo tty8 still logged in (unknown tty8 1351897200 - 1351897200 (00:00) date: błędna data: `pablo tty2 Thu Nov 1 12:50:39 2012 still logged in ' pablo tty2 1351897200 still logged in date: błędna data: `pablo tty7 Thu Nov 1 12:49:45 2012 - Thu Nov 1 12:50:56 2012 (00:01) ' pablo tty7 1351897200 - 1351897200 (00:01) (unknown tty7 1351897200 - 1351897200 (00:15) 

Как улучшить приведенную выше команду?

Чтобы сделать это по-своему, это должно быть чем-то вроде:

 POSIXLY_CORRECT=1 awk ' { n = ""; r = $0 while (match(r, /[[:alpha:]]{3} [[:alpha:]]{3} +[0-9]+ ([0-9]{2}:){2}[0-9]{2} [0-9]{4}/)) { c = "date -d\"" substr(r,RSTART,RLENGTH) "\" +%s" c | getline b close(c) n = n substr(r,1,RSTART-1) b r = substr(r,RSTART+RLENGTH) } print nr }' 

Вот альтернативный подход (с использованием mktime ):

 #!/bin/awk -f { split($6,A,":"); S1=sprintf("%d %d %d %d %d %d",$7,$4,$5,A[1],A[2],A[3]) T1=mktime(S1) if ($8=="-") { split($12,A,":"); S2=sprintf("%d %d %d %d %d %d",$13,$10,$11,A[1],A[2],A[3]) T2=mktime(S2) print $1,$2,T1,$8,T2,$14 } else { print $1,$2,T1,$8,$9,$10 } } , #!/bin/awk -f { split($6,A,":"); S1=sprintf("%d %d %d %d %d %d",$7,$4,$5,A[1],A[2],A[3]) T1=mktime(S1) if ($8=="-") { split($12,A,":"); S2=sprintf("%d %d %d %d %d %d",$13,$10,$11,A[1],A[2],A[3]) T2=mktime(S2) print $1,$2,T1,$8,T2,$14 } else { print $1,$2,T1,$8,$9,$10 } } , #!/bin/awk -f { split($6,A,":"); S1=sprintf("%d %d %d %d %d %d",$7,$4,$5,A[1],A[2],A[3]) T1=mktime(S1) if ($8=="-") { split($12,A,":"); S2=sprintf("%d %d %d %d %d %d",$13,$10,$11,A[1],A[2],A[3]) T2=mktime(S2) print $1,$2,T1,$8,T2,$14 } else { print $1,$2,T1,$8,$9,$10 } } 

Вы можете сделать это с помощью GNU sed:

convert_date.sed

 : a s/(([A-Za-z]{3} ){2}[0-9]{1,2} ([0-9]{2}:){2}[0-9]{2} [0-9]{4})(.*)/\n\4\n\1/ h s/.*\n// s/^/date -d "/ s/$/" +%s/e G s/([^\n]+)\n([^\n]+)\n([^\n]+)\n.*/\2\1\3/ /([A-Za-z]{3} ){2}[0-9]{1,2} ([0-9]{2}:){2}[0-9]{2} [0-9]{4}/ta 

Выполните его следующим образом:

 sed -rf convert_date.sed infile 

Вывод:

 pablo tty8 1351770681 still logged in (unknown tty8 1351770657 - 1351770681 (00:00) pablo tty2 1351770639 still logged in pablo tty7 1351770585 - 1351770656 (00:01) (unknown tty7 1351769672 - 1351770585 (00:15) 

объяснение

Сначала это может показаться немного сложным, но идея не такая уж сложная. Это регулярное выражение ([A-Za-z]{3} ){2}[0-9]{1,2} ([0-9]{2}:){2}[0-9]{2} [0-9]{4} , который встречается в первой замене и в конце условного, соответствует типу даты, используемому во вводе, он фиксирует и изолирует дату. Окружающие биты хранятся в пространстве удержания, а date -d запускается на захваченную дату. Наконец, все биты собираются в пространстве шаблонов и реорганизуются в правильный порядок.

Условие в конце повторяет процесс, если какие-либо даты остаются в пространстве шаблонов.

С perl и его модулем Date::Manip :

 perl -MDate::Manip -pe ' s/\w{3} \w{3} +\d+ \d\d:\d\d:\d\d \d+/ UnixDate ParseDate("$&"),"%s"/ge' 

Решение Perl, предоставляемое Stephane, требует неявного модуля Perl. Можно использовать основной модуль (начиная с 5.10), Time :: Piece , аналогично:

 #!/usr/bin/env perl use strict; use warnings; use Time::Piece; my $t = Time::Piece->new; while (<>) { s{\w{3}\s(\w{3}\s\d{1,2}\s\d\d:\d\d:\d\d\s\d{4})} {$t=Time::Piece->strptime($1,"%b %d %H:%M:%S %Y"); sprintf "%s",$t->epoch}ge; print; }