ファイル形式は次のとおりです。
aaa 1-00:12:43.122
aaa 0-21:14:43.133
bbb 3-11:14:54.433
bbb 2-00:00:10
2番目の列の数字は形式ですd-hh:mm:ss.nnn
。場合によっては、最後の10進3桁は存在しません。各ユーザーの合計持続時間を得るために、最初の列にグループ化して合計する方法を見つけようとしています。したがって、この例の結果は次のようになります。
aaa 1-21:27:26.255
bbb 5-11:15:04.433
答え1
次のawk
スクリプトを使用してください。
BEGIN {
FS=" |-|:"
}
{
data[$1][2]+=$2
data[$1][3]+=$3
data[$1][4]+=$4
data[$1][5]+=$5
}
END {
for( record in data ) {
if( data[record][5]>=60 ) {
data[record][4]+=1
data[record][5]-=60.0
}
if( data[record][4]>=60 ) {
data[record][3]+=1
data[record][4]-=60
}
if( data[record][3]>=24 ) {
data[record][2]+=1
data[record][3]-=24
}
printf( "%s %d-%02.0f:%02.0f:%06.3f\n", record, data[record][2], data[record][3], data[record][4], data[record][5] )
}
}
使用法:
~/scratch/se/379631$ cat input
aaa 1-00:12:43.122
aaa 0-21:14:43.133
bbb 3-11:14:54.433
bbb 2-00:00:10
~/scratch/se/379631$ gawk -f 379631.awk input
aaa 1-21:27:26.255
bbb 5-11:15:04.433
答え2
AND perl
、ハッシュ値の使用日時::形式::期間モジュール、正規表現置換を使用してナノ秒を正規化します。
perl -MDateTime::Format::Duration -ane '
BEGIN {
$p = DateTime::Format::Duration->new(pattern => "%e-%H:%M:%S.%N");
}
$F[1] =~ s/\d+(\.\d+)?$/sprintf "%02.9f", $&/e;
$h{$F[0]} = $h{$F[0]} ? $dt->add_duration($h{$F[0]}) : $dt if $dt = $p->parse_duration($F[1]);
END {
$p = DateTime::Format::Duration->new(pattern => "%e-%H:%M:%S.%3N", normalize => 1);
for $k (sort keys %h) {printf "%s %s\n", $k, $p->format_duration($h{$k})}
}
' file
aaa 1-21:27:26.255
bbb 5-11:15:04.433
答え3
perl -F'\h+|[-.:]' -lane '
$h[keys %h]=$F[0] unless $h{$F[0]};
$h{$F[0]}[$_-1] += $F[$_] for 1..$#F}{for ( @h )
{
my @Arefs = map { \$_ } my($days, $hrs, $mins, $secs, $msec) = @{$h{$_}};
while ( $msec >= 1000 ) { $secs++; $msec -= 1000; }
while ( $secs >= 60 ) { $mins++; $secs -= 60; }
while ( $mins >= 60 ) { $hrs++; $mins -= 60; }
while ( $hrs >= 24 ) { $days++; $hrs -= 24; }
print $_, sprintf " %d-%02d:%02d:%02d.%03d", map $$_, @Arefs;
}
' text.file
perl -F'\h+|[-.:]' -lane '
$h[keys %h]=$F[0] unless $h{$F[0]};
$h{$F[0]}[$_-1] += $F[$_] for 1..$#F}{for ( @h )
{
use integer;
my @A = @{$h{$_}};
$A[0] += ($A[1] += ($A[2] += ($A[3] += $A[4]/1000)/60)/60)/24;
$A[4] %= 1000; $A[3] %= 60;$A[2] %= 60; $A[1] %= 24;
print $_, sprintf " %d-%02d:%02d:%02d.%03d", @A;
}
' text_file
結果
aaa 1-21:27:26.255
bbb 5-11:15:04.433
説明する
- フィールド区切り記号は、ミリ秒、秒、分、時間、日、および最初のフィールドキーを区切るように設定されます。
@F
入力行は分割され、次の要素を含む配列に格納されます。$ F [0] - >キー(aaa / bbb / etc) F[3] -> 分、 $F[4] -> 秒、 $F[5] -> ミリ秒。- ハッシュキーは本質的に生成された順序でアクセスされないため、表示される順序で
@h
ハッシュキーを要素とする配列があります。%h
- ハッシュは
%h
次のように構成されます。
%h = (
aaa => [ days, hours, minutes, seconds, milliseconds ],
bbb => [ ... ],
...
);