awk如何按列号查询

awk如何按列号查询

我想获取由,以下命令分隔的第 2 列的时间差。默认情况下,第一列工作正常。

桌子:

20220505,12:00:12,user,dept
20220505,12:00:25,user,dept
20220505,12:00:32,user,dept

命令:

awk -F: '{t=$1*3600+$2*60+$3} NR>1{printf( "%.6f\n", t-p)}{p=t}' inputfile

我尝试过:但未能得到正确的结果。

awk -F ',' $2 '{t=$1*3600+$2*60+$3} NR>1{printf( "%.6f\n", t-p)}{p=t}' inputfile

答案1

你需要告诉 awk 使用两个都 ,:作为字段分隔符。请注意,这将更改字段的编号(因为两个字段分隔符都应用于每个输入行)。例如:

$ awk -F '[:,]' '{ t = $2*3600 + $3*60 + $4 }
                 NR > 1 { printf "%.6f\n", t-p }
                 { p=t }' inputfile
13.000000
7.000000

请注意,这不会计算不同日期的时间差。为此,您需要将组合的日期和时间解析为一个time_t值(即自纪元(1970 年 1 月 1 日午夜)以来的秒数)。例如,与GNUawk,使用以下mktime()函数:

$ awk -F '[:,]' '{
                    # extract the year, month, and day from the first field
                    y = substr($1,1,4);
                    m = substr($1,5,2);
                    d = substr($1,7,2);
                    # create a space-separated datespec string, combining y,m,d with
                    # hours, minutes, and seconds from fields 2, 3, and 4
                    datespec = y " " m " " d " " $2 " " $3 " " $4;
                    # convert it to seconds since the epoch
                    t = mktime(datespec)
                  }
                  NR > 1 { printf "%.6f\n", t-p }
                  { p=t }' inputfile
13.000000
7.000000

运行man awk并搜索mktime有关此函数如何工作的摘要。

答案2

使用(以前称为 Perl_6)

raku -e 'my @a = lines.map: *.split(",");  my @b; for ^@a.elems -> $i {  \
         my $date = @a[$i][0].subst(/ ^ (\d**4)(\d**2)(\d**2) $/, {"$0-$1-$2"});  \
         @b.push: "{$date}T@a[$i][1]Z".DateTime.Instant };  \
         loop (my $i = 0; $i < @b.elems-1; $i++) { put @b[$i+1] - @b[$i] };'

Raku 使用以下方法处理日期和时间ISO 8601 互换标准, 内置。在第一个语句中,每个都以逗号lines读入,并保存在数组中。数组已声明。然后循环行,第一列(日期)的元素创建连字符分隔,并且该字符串用于生成 ISO 8601之类的.这会立即转换为一个对象(以秒为单位)并添加到数组中。在最后的语句中,秒数被遍历并相互减去。split","@a@bsubst-$dateDateTime2022-05-05T12:00:12ZDateTimeInstantpush@bInstantloop

输入示例 1:

20220505,12:00:12,user,dept
20220505,12:00:25,user,dept
20220505,12:00:32,user,dept

示例输出1:

13
7

使用日期和时间的优点如下ISO 8601:正确处理从一个日期到下一个日期的时间戳。

输入示例 2:

20220505,23:59:45,user,dept
20220506,00:00:00,user,dept
20220506,00:00:15,user,dept

示例输出 2:

15
15

https://en.wikipedia.org/wiki/ISO_8601
https://docs.raku.org/language/temporal#index-entry-Date_and_time_functions
https://raku.org

相关内容