ddMMyyyy-HHmm+0300
私は私のタイムスタンプ形式()をWEKAデータ分析システムで使用されるタイムスタンプ/時間/...形式()に変換するPerl / ...メソッドを考案したいと思います。元のコマンドでyyyy-MM-dd'T'HH:mm:00
WEKAデータファイルを作成します。私の考えには(3)番の方法が最も妥当だと思います。つまり、(Deathgrip)関数を直接使用することです。paste
AWK
POSIX::strftime
- セクション1の難しさ
- セクション2のデータに引用符を使用しない簡単な方法
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
-
文字通りHH
24([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" } );
1行の出力が期待どおりです。
"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.
オペレーティングシステム:Debian 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)
2つの連続した数字をキャプチャし、(\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