考虑以下文件摘录:
19610101 060000 0.4 G
19610101 120000 2.3 G
19610101 180000 ... .
19610102 150000
19610102 180000
19610103 060000
........ ......
20150901
最左边的列指定日期。如果想要插入一列,将一年中的某一天指定为 1-365/366 之间的数字,该如何做呢?
如果要提取每个日期的最后四位数字,即 0101,0102,...,则会得到一个递归且递增的数字序列。从那里我们会去哪里?或者有更简单的实现吗?
答案1
给定文件file
内容
19610101 060000 0.4 G
19610101 120000 2.3 G
19610101 180000 ... .
19610102 150000 ... .
19610102 180000 ... .
19610103 060000 ... .
20150901 ...... ... .
我们可以使用 GNUawk
或mawk
(两者都有mktime()
和strftime()
):
awk '
{
tspec = sprintf("%4d %.2d %.2d 00 00 00", substr($1,1,4), substr($1,5,2), substr($1,7,2))
t = mktime(tspec)
$(NF+1) = strftime("%j",t)
} { print }' file
t
这将根据从文件第一列解析的日期创建一个 Unix 时间戳(使用午夜作为时间)。然后,它使用格式strftime()
来格式化时间戳%j
,这将为我们提供一年中的某一天,作为一个零填充的整数(请参阅参考资料man strftime
)。该数字将作为新列插入,然后打印该行。
结果:
19610101 060000 0.4 G 001
19610101 120000 2.3 G 001
19610101 180000 ... . 001
19610102 150000 ... . 002
19610102 180000 ... . 002
19610103 060000 ... . 003
20150901 ...... ... . 244
要摆脱零填充,请使用$(NF+1) = 0 + strftime(...)
.
答案2
如果您的数据是同质的,例如。
$ cat file
Date Time
19610101 060000
19610101 120000
19610101 060000
19610102 120000
19610102 060000
19610102 120000
20150901 060000
那么 Miller ( mlr
) 可能是一个不错的选择:
$ mlr --pprint --fs " " --repifs put -S '
$Day = strftime(strptime($Date,"%Y%m%d"),"%j")
' file
Date Time Day
19610101 060000 001
19610101 120000 001
19610101 060000 001
19610102 120000 002
19610102 060000 002
19610102 120000 002
20150901 060000 244
请注意使用-S
来将未分隔的YYYYmmmdd
字段强制转换为字符串类型strptime
(默认情况下,它被解析为整数)。