이 타임스탬프 형식을 Perl의 다른 형식으로 어떻게 변환할 수 있습니까?

이 타임스탬프 형식을 Perl의 다른 형식으로 어떻게 변환할 수 있습니까?

ddMMyyyy-HHmm+0300나는 내 타임스탬프 형식( )을 WEKA 데이터 분석 시스템에서 사용하는 타임스탬프/시간/... 형식( ) 으로 변환하는 Perl/... 메서드를 고안하려고 합니다 . 원래는 명령을 통해 yyyy-MM-dd'T'HH:mm:00WEKA 데이터 파일을 만들고 . 제 생각엔 (3)번 방법이 가장 타당하다고 생각합니다. 즉, (Deathgrip) 함수를 직접 사용하는 것입니다.pasteAWKPOSIX::strftime

  1. 섹션 1의 어려움
  2. 섹션 2의 데이터에 따옴표를 사용하지 않는 더 쉬운 방법
  3. POSIX::strftime방법 및 유사한 스레드Perl strptime 형식은 strftime과 다릅니다.

입력 예

23072017-2200+0300
  • 예상 출력

    2017-07-23'T'22:00:00
    

따옴표는 없지만 밑줄이 포함된 CSV 줄의 전체 예이므로 더 어려울 수 있습니다.

 Ni, Aika, Aika_l, Un, Unen, Unen_kesto, Uniluokat_R, Uniluokat_k, Uniluokat_s, HRV_RMSSD_a, HRV_RMSSD_i, Kokonaisp, Palautumisen_k, Hermoston_t, Syke_ave_m, Syke_a, Syke_l, Hengitystiheys_ave_m, Hengitystiheys_a, Hengitystiheys_min_a, Liikeaktiivisuus_l, Liikeaktiivisuus_a, Paivamaara_l
 "Masi", 23072010-2200+0300, 24072010-0600+0300, 70, 7h40, 6h30, 1h40, 3h40, 1h10, 67.0, 43.0, 24.0, 430, 30, 70, 50, 40, 20, 10, 10, 150, 260, 24.10.2010
 "Masi", 23072010-2200+0300, 24072010-0600+0300, 70, 7h40, 6h30, 1h40, 3h40, 1h10, 67.0, 43.0, 24.0, 430, 30, 70, 50, 40, 20, 10, 10, 150, 260, 24.10.2010

예상 출력

 Ni, Aika, Aika_l, Un, Unen, Unen_kesto, Uniluokat_R, Uniluokat_k, Uniluokat_s, HRV_RMSSD_a, HRV_RMSSD_i, Kokonaisp, Palautumisen_k, Hermoston_t, Syke_ave_m, Syke_a, Syke_l, Hengitystiheys_ave_m, Hengitystiheys_a, Hengitystiheys_min_a, Liikeaktiivisuus_l, Liikeaktiivisuus_a, Paivamaara_l
 "Masi", 2010-07-23'T‌​'22:00:00, 2010-07-24'T‌​'06:00:00, 70, 7h40, 6h30, 1h40, 3h40, 1h10, 67.0, 43.0, 24.0, 430, 30, 70, 50, 40, 20, 10, 10, 150, 260, 24.10.2010
 "Masi", 2010-07-23'T‌​'22:00:00, 2010-07-24'T‌​'06:00:00, 70, 7h40, 6h30, 1h40, 3h40, 1h10, 67.0, 43.0, 24.0, 430, 30, 70, 50, 40, 20, 10, 10, 150, 260, 24.10.2010

1. 호출할 수 있는 스크립트를 사용해 보세요.script.pl filename

Text::CSV내 데이터 세트가 사용 사례보다 단순하기 때문에 파서가 사용하기에는 너무 복잡하다고 생각합니다 . 그래서 간단한 정규식 접근 방식이 가능하다고 생각합니다.

#!/usr/bin/env perl
# https://stackoverflow.com/a/33995620/54964

## Data prepared like this for the script
# paste -d" " log.csv data.csv | awk '{$1=""; print $0}' > weka.data.csv
# cp $HOME/Data/weka.data.csv $HOME/Workspace/
#
# Maybe, this all could be integrated into Perl script

use strict;
use warnings;

use Text::CSV;

my $csv = Text::CSV->new( { binary => 1, eol => "\n" } );

while ( my $row = $csv->getline( \*ARGV ) ) {
    s/\n/ /g for @$row;
    $csv->print( \*STDOUT, $row );

    # TODO regex
    #convert ddMMyyyy-HHmm+0300 to yyyy-MM-dd'T'HH:mm:00    
}

2. Perl 정규 표현식 방법

변수 대체가 없기 때문에(예: dd결과 전달) 메서드에 대한 의사 코드가 작동하지 않습니다.

# TODO s/ddMMyyyy-HHmm+0300/$3-$2-$1'T'$4:$5:00/;
perl -pe s/([0-3][0-9])(([0-1][0-9]))(20[0-9]{2})([0-2][0-9])([0-5][0-9])+0300/$3-$2-$1'T'$4:$5:00/;

어디

  • dd통과 ([0-3][0-9])/$3
  • 마찬가지로 / MM의 경우([0-1][0-9])$2
  • yyyy비슷하다 (20[0-9]{2})/$1
  • -문자 그대로
  • HH24시간 ([0-5][0-9])/$4
  • mm통과 ([0-5][0-9])) /$5
  • +0300/ 간단히 삭제

정규식에 더 읽기 쉬운 형식이 있으면 좋을 것입니다.

댓글로 Sundeep의 제안을 테스트해 보세요.

암호

#!/bin/bash
# https://stackoverflow.com/a/33995620/54964

s='"Masi", 23072010-2200+0300, 24072010-0600+0300 70, 7h40'

echo "$s" | perl -pe 's/\b(\d\d)(\d\d)(\d{4})-(\d\d)(\d\d)\+\d{4}\b/$3-$2-$1\x27T<200c><200b>\x27$4:$5:00/g' y $csv = Text::CSV->new( { binary => 1, eol => "\n" } );

한 줄의 출력이 예상대로입니다.

"Masi", 2010-07-23'T‌​'22:00:00, 2010-07-24'T‌​'06:00:00, 70, 7h40

변수 내용을 바꾸는 것만으로도 전체 라인에 적용되어 s예상대로 출력됩니다.

"Masi", 2010-07-23'T‌​'22:00:00, 2010-07-24'T‌​'06:00:00, 70, 7h40, 6h30, 1h40, 3h40, 1h10, 67.0, 43.0, 24.0, 430, 30, 70, 50, 40, 20, 10, 10, 150, 260, 24.10.2010

여러 줄 방법과 헤더 건너뛰기 기능을 갖춘 TODO 완전한 방법

Deathgrip 테스트에 대한 적극적인 제안

암호

#!/usr/bin/env perl
# https://stackoverflow.com/a/33995620/54964

use strict;
use warnings;
# https://stackoverflow.com/a/20007784/54964
# http://perldoc.perl.org/POSIX.html
use Time::Piece;
use POSIX;

# TODO breaks because of false brackets
#my $input = '"Masi", 2010-07-23'T<200c><200b>'22:00:00, 2010-07-24'T<200c><200b>'06:00:00, 70, 7h40, 6h30, 1h40, 3h40, 1h10, 67.0, 43.0, 24.0, 430, 30, 70, 50, 40, 20, 10, 10, 150, 260, 24.10.2010'

my $str = '23072017-2200+0300';
my $f = '%d%m%dY-%H%M+0300';
#my $t = POSIX::strftime($str, $f); # fails!
my $t = strftime($str, $f); # fails!

print "$t\n";

산출

Usage: POSIX::strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1) at prepare.data3.pl line 22.

운영 체제: 데비안 9

답변1

$ perl -pe 's/\b(\d\d)(\d\d)(\d{4})-(\d\d)(\d\d)\+\d{4}\b/$3-$2-$1\x27T\x27$4:$5:00/g' ip.csv
 Ni, Aika, Aika_l Un, Unen, Unen_kesto, Uniluokat_R, Uniluokat_k, Uniluokat_s, HRV_RMSSD_a, HRV_RMSSD_i, Kokonaisp, Palautumisen_k, Hermoston_t, Syke_ave_m, Syke_a, Syke_l, Hengitystiheys_ave_m, Hengitystiheys_a, Hengitystiheys_min_a, Liikeaktiivisuus_l, Liikeaktiivisuus_a, Paivamaara_l
 "Masi", 2010-07-23'T'22:00:00, 2010-07-24'T'06:00:00 70, 7h40, 6h30, 1h40, 3h40, 1h10, 67.0, 43.0, 24.0, 430, 30, 70, 50, 40, 20, 10, 10, 150, 260, 24.10.2010
 "Masi", 2010-07-23'T'22:00:00, 2010-07-24'T'06:00:00 70, 7h40, 6h30, 1h40, 3h40, 1h10, 67.0, 43.0, 24.0, 430, 30, 70, 50, 40, 20, 10, 10, 150, 260, 24.10.2010
  • \b단어 경계입니다
  • (\d\d)두 개의 연속 숫자를 캡처하고 (\d{4})그 중 4개를 캡처하는 등의 작업을 수행합니다.
  • \x27작은따옴표에 사용됩니다. 그 뒤에 관련 없는 숫자가 있을 수 있는 경우 8진수 표현을 사용하는 것이 더 나을 수도 있습니다.\047
  • 검색 및 바꾸기는 특정 ddMMyyyy-HHmm+0300형식만 대상으로 하기 때문에 헤더에는 영향을 주지 않습니다. 하지만 필요한 경우 if $.>1대체 명령 뒤에 추가하면 됩니다.

paste+awk입력을 생성하는 데 사용된 명령을 이 명령에 쉽게 통합할 수 있지만 해당 정보를 질문에 추가해야 합니다 .

답변2

내가 할 일은 다음과 같습니다.

#!/usr/bin/env perl
# https://stackoverflow.com/a/33995620/54964

use strict;
use warnings;
# https://stackoverflow.com/a/20007784/54964
# http://perldoc.perl.org/POSIX.html
use POSIX qw(strftime);
use DateTime;
use DateTime::Format::Strptime qw(strptime);

my $str = '23072017-2200+0300';
my $dtime = strptime( '%d%m%Y-%H%M%z', $str );
my $f = '%Y-%m-%d\'T\'%H:%M:%S';
my $t = strftime( $f, 0, $dtime->minute, $dtime->hour, $dtime->day, $dtime->month-1, $dtime->year-1900, -1, -1, $dtime->time_zone );

print "$t\n";

시간 필드에서 예상대로 출력

2017-07-23'T'22:00:00

관련 정보