我有一个用逗号分隔的输入文件,其中有7列,其中:
yyyymmdd
HHMMSS
格式的时间。我想通过在合并的日期时间格式中添加一小时来更新这两列。这意味着:
HH
<23,仅更新第四列HH
> = 23,请在移至第二天的同时更新两列。下面您将找到我的尝试之一,其中包含输入和预期输出。
评论:正如下面的评论中指出的那样,我无权访问GNU awk。因此,当我使用时间函数strftime
awk 'BEGIN { FS=OFS="," }
{
if($4<230000)
$4=sprintf("%06d",$4+10000)
else
{
$4=sprintf("%06d",$4-230000)
$3+=86400
}
print
}' Test.txt > A.txt
样本数据:
1039,1018,20180915,000000,0,0,A
1039,1018,20180915,010000,0,0,A
1039,1018,20180915,020000,0,0,A
1039,1018,20180915,030000,0,0,A
1039,1018,20180915,240000,0,0,A
预期输出:
1039,1018,20180915,010000,0,0,A
1039,1018,20180915,020000,0,0,A
1039,1018,20180915,030000,0,0,A
1039,1018,20180915,040000,0,0,A
1039,1018,20180916,010000,0,0,A
答案 0 :(得分:3)
使用系统命令将1天添加到第3列
awk '
BEGIN { FS=OFS="," }
{
if($4<230000)
$4=sprintf("%06d",$4+10000)
else {
$4=sprintf("%06d",$4-230000)
date="$( date -d '19500101')";
#print strftime("%Y%m%d",$3);
#$3+=86400
# # GNU date
# $3 = strftime("%Y%m%d", (24*3600)+mktime(substr($3,1,4)" "substr($3,5,2)" "substr($3,7)" 00 00 00"))
# BSD date
$3=((sprintf("date -j -v+1d -f \"%%Y%%m%%d\" %s \"+%%Y%%m%%d\"", $3) | getline line) > 0 ? line: "INVALID DATE" )
}
print
}' Test.txt
date
命令是GNU date
。参见GNU Coreutils: date invocation
如果您在macOS上运行此脚本,请确保已安装coreutils
。如果没有,请使用brew
进行安装。
brew install coreutils
更新
不再使用date
命令。结合@ ExpertNoob1的答案。
awk '
BEGIN { FS=OFS="," }
{
if($4<230000)
$4=sprintf("%06d",$4+10000)
else {
$4=sprintf("%06d",$4-230000)
date="$( date -d '19500101')";
#print strftime("%Y%m%d",$3);
#$3+=86400
$3 = strftime("%Y%m%d", (24*3600)+mktime(substr($3,1,4)" "substr($3,5,2)" "substr($3,7)" 00 00 00"))
}
print
}' Test.txt
答案 1 :(得分:2)
在没有可用的GNU awk扩展的情况下,我认为这可能就是您真正想要的。
#!/usr/bin/awk -f
BEGIN {
OFS=FS=","
split("31 28 31 30 31 30 31 31 30 31 30 31", days, " ")
}
{
# Add one hour to the current time
$4=sprintf("%06d", $4 + 10000 )
# Is this a leap year?
year=substr($3,1,4)
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
days[2]=29
} else {
days[2]=28
}
}
# too many hours
$4 >= 240000 {
$3=$3 + int($4/240000) # add days for sets of 24 hours
$4=sprintf("%06d", $4 % 24000 ) # reduce time to < 24 hours
# too many days
if (substr($3,7,2) > days[substr($3,5,2)+0]) {
$3=sprintf( "%04d%02d%02d", substr($3,1,4), substr($3,5,2)+1, substr($3,7,2)-days[substr($3,5,2)+0] )
# too many months
if (substr($3,5,2) > 12) {
$3=sprintf( "%04d%02d%02d", substr($3,1,4)+1, substr($3,5,2)-12, substr($3,7,2) )
}
}
}
# print the line
1
这会从最小的单元到最大的单元逐步进行重大超量。显然可以将其压缩一点。事情散布开来进行评论。
似乎可以处理您的数据。以及大约leap年的日期和时间。我没有进一步测试。
请注意,它没有考虑DST转换或leap秒。
答案 2 :(得分:2)
好像我对您的情况读得不够仔细。正如一些人指出的那样,这是使用GNU awk的替代解决方案。
#!/usr/bin/awk -f
BEGIN { FS=OFS="," }
{
if($4<230000)
$4=sprintf("%06d",$4+10000)
else
{
$4=sprintf("%06d",$4-230000)
year=substr($3, 1,4)
month=substr($3, 5,2)
day=substr($3, 7,2)
dstr=year " " month " " day " 00 00 00"
dstamp=mktime(dstr)
dstamp+=86400
$3=strftime("%Y%m%d",dstamp)
}
print
}
$ ./script.awk Test.txt
1039,1018,20180915,010000,0,0,A
1039,1018,20180915,020000,0,0,A
1039,1018,20180915,030000,0,0,A
1039,1018,20180915,040000,0,0,A
1039,1018,20180916,010000,0,0,A
答案 3 :(得分:1)
$3 = strftime("%Y%m%d", (24*3600)+mktime(substr($3,1,4)" "substr($3,5,2)" "substr($3,7)" 00 00 00"))