범용 텍스트 파일의 모든 Unix 타임스탬프(밀리초 단위)를 사람이 읽을 수 있는 날짜로 변환합니다.

범용 텍스트 파일의 모든 Unix 타임스탬프(밀리초 단위)를 사람이 읽을 수 있는 날짜로 변환합니다.

일반 텍스트 파일의 Unix Epoch(밀리초)를 일반 날짜로 변경하고 싶습니다. 나는 bash, sed, awk 또는 perl 솔루션을 허용합니다.

예시 파일1(13자리만 날짜임):

Foo bar 1397497040418 foo 1526 bar foobar, bar 1397497060518.
Bar, 1357407040418 foo 10 foobar.

나는 다음과 같은 출력을 원합니다.

Foo bar 2014-04-14 19:37:20 foo 1526 bar foobar, bar 2014-04-14 19:37:40.
Bar, 2013-01-05 18:30:40 foo 10 foobar.

내 시도가 실패했습니다:

sed -E "s/([0-9]{10})/date -d @\1/;e" file1

어떤 아이디어가 있나요?

감사해요.

답변1

입력 파일을 사용하십시오.

perl -MTime::Piece -pe '
    s{ \b (\d{10}) \d{3}\b }
     { localtime($1)->strftime("%F %T") }xge
' file1
Foo bar 2014-04-14 13:37:20 foo 1526 bar foobar, bar 2014-04-14 13:37:40.
Bar, 2013-01-05 12:30:40 foo 10 foobar.

답변2

추가 숫자를 무시하고 날짜 변환을 처음 10자리로만 제한하기를 원한다고 가정하면(즉, 날짜가 수십만 년 후가 아님을 의미) GNU를 사용하여 date다음과 같이 할 수 있습니다 perl.

$ perl -pe 's/\b(\d{10})\d{3}\b/chomp($i=`date -d \@$1 "+%F %T"`);$i/eg' file1 
Foo bar 2014-04-14 18:37:20 foo 1526 bar foobar, bar 2014-04-14 18:37:40.
Bar, 2013-01-05 17:30:40 foo 10 foobar.

글렌의 솔루션그러나 더 깨끗하고 이식성이 높으므로 Perl 모듈을 사용하는 것이 마음에 들지 않는다면 (그리고 그렇게 해서도 안 됩니다), 저는 제 것보다 이 모듈을 추천합니다.


귀하의 sed시도에 관해서는결과명령의 경우 백틱 또는 를 사용해야 합니다 $(command). 이제 거의 다 왔습니다.

$ sed -E "s/([0-9]{10})/$(date -d @\1)/" file1
Foo bar Thu 01 Jan 1970 01:00:01 AM BST418 foo 1526 bar foobar, bar 1397497060518.
Bar, Thu 01 Jan 1970 01:00:01 AM BST418 foo 10 foobar.

물론 이것은 추가 숫자를 제거하지도 않고 13자리로만 제한하지도 않지만 필요한 것이 무엇인지 명확하게 지정하지 않았으므로 수정 방법을 모르겠습니다. 내 Perl 솔루션이 이를 처리하므로 제거하고 싶지 않으면 sed를 사용할 수 있습니다.

답변3

및 기능 과 awk함께 GNU를 사용하십시오 . EPOCH 타임스탬프이기 때문에 주어진 행을 스캔하여 10개 이상의 숫자가 포함된 레코드를 식별하세요.match()substr()strftime()

이 레코드에서 처음 10자리만 추출하여 strftime()함수에 전달하고 필요한 경우 날짜 형식을 적용합니다. 이 기능을 사용하여 원본 레코드를 새 타임스탬프로 교체합니다 sub().

awk '
{ 
    for(col=1; col<=NF; col++) { 
        if ( match($col, /[[:digit:]]{10,}/) ) { 
            sub( substr($col, RSTART, RLENGTH), 
              strftime("%Y-%m-%d %H:%M:%S", substr($col, RSTART, RLENGTH-3) ) )   
        }  
    }
}1' file1

답변4

GNU awk 시간 함수의 경우 match() 및 단어 경계에 대한 세 번째 인수는 다음과 같습니다.

$ awk '{
    while ( match($0,/(.*)\<([0-9]{10})[0-9]{3}\>(.*)/,a) ) {
        $0 = a[1] strftime("%F %T",a[2]) a[3]
    }
    print
}' file
Foo bar 2014-04-14 12:37:20 foo 1526 bar foobar, bar 2014-04-14 12:37:40.
Bar, 2013-01-05 11:30:40 foo 10 foobar.

관련 정보