형식화된 날짜를 에포크 이후의 초로 변환

형식화된 날짜를 에포크 이후의 초로 변환

파일이 있습니다:

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)

위 명령을 어떻게 개선할 수 있나요?

답변1

다음은 다른 방법입니다( 사용 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
    }
}

답변2

원하는 방식으로 수행하려면 다음과 같아야 합니다.

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 n r
  }'

답변3

GNU sed를 사용하여 이 작업을 수행할 수 있습니다.

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캡처된 날짜에 실행 하면 주변 비트가 예약된 공간에 저장됩니다. 마지막으로 모든 비트가 패턴 공간에 수집되어 올바른 순서로 재구성됩니다.

패턴 공간에 아직 날짜가 있으면 마지막 조건이 프로세스를 반복합니다.

답변4

Stephane이 제공하는 Perl 솔루션에는 비핵심 Perl 모듈이 필요합니다. 핵심 모듈을 사용할 수 있습니다(5.10부터).시간::조각, 마찬가지로:

#!/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;
}

관련 정보