我是Shell脚本的新手。我有一个制表符分隔的文件,例如
0018803 01 1710 2050 002571
0018951 01 1934 2525 003277
0019362 02 2404 2415 002829
0019392 01 2621 2820 001924
0019542 01 2208 2413 003434
0019583 01 1815 2134 002971
在这里,第3和第4列分别代表开始时间和结束时间。
我想在适当的timeFrame中转换这两列,以便我可以得到第6列,即第4
列和第3
列之间的精确时差,以小时和分钟为单位。
第6
列的结果将是3:40
,5:51
,00:11
,1:59
,2:05
。
答案 0 :(得分:2)
使用awk
的一种方式:
$ cat test.awk
# create a function to split hour and minute
function f(h, x) {
h[0] = substr(x,1,2)+0
h[1] = substr(x,3,2)+0
}
{
f(start, $3);
f(end, $4);
span = end[1] - start[1] > 0 \
? sprintf("%d:%02d", end[0]-start[0], end[1]-start[1]) \
: sprintf("%d:%02d", end[0]-start[0]-1, 60+end[1]-start[1]);
print $0 OFS span
}
然后按以下方式运行awk文件:
$ awk -f test.awk input_file
编辑:根据@glenn jackman的建议,可以简化代码(请参阅@Kamil Cuk的方法):
function g(x) {
return substr(x,1,2)*60 + substr(x,3,2)
}
{
span = g($4) - g($3)
printf("%s%s%d:%02d\n", $0, OFS, int(span/60), span%60)
}
答案 1 :(得分:2)
使用算术扩展的简单bash解决方案:
while IFS='' read -r l; do
IFS=' ' read -r _ _ st et _ <<<"$l"
d=$(( (10#${et:0:2} * 60 + 10#${et:2:2}) - (10#${st:0:2} * 60 + 10#${st:2:2}) ))
printf "%s %02d:%02d\n" "$l" "$((d/60))" "$((d%60))"
done < intput_file_path
将输出:
0018803 01 1710 2050 002571 03:40
0018951 01 1934 2525 003277 05:51
0019362 02 2404 2415 002829 00:11
0019392 01 2621 2820 001924 01:59
0019542 01 2208 2413 003434 02:05
0019583 01 1815 2134 002971 03:19
答案 2 :(得分:1)
这是GNU awk中使用time functions,mktime
转换为纪元时间和strftime
将时间转换为所需格式HH:MM
的人:
$ awk -v OFS="\t" '{
dt3="1970 01 01 " substr($3,1,2) " " substr($3,3,2) " 00"
dt4="1970 01 01 " substr($4,1,2) " " substr($4,3,2) " 00"
print $0,strftime("%H:%M",mktime(dt4)-mktime(dt3),1) # thanks @glennjackman,1 :)
}' file
输出(仅$ 6):
03:40
05:51
00:11
01:59
02:05
03:19