将时间戳包含到 awk 命令中

将时间戳包含到 awk 命令中

考虑一堆几乎相同的 csv 文件。它们都有共同的部分,即一行后面跟着Date;Time;...四列数据(一些第一行有六列,其中第五列是空的,第六列只是描述性文本)。行前还有分隔成各个列的描述性文本Date;Time;...

...
...
Date;Time;Airtemp;Quality;;Other info
1961-01-01;06:00:00;0.4;G;;...
1961-01-01;12:00:00;2.3;G;;...
1961-01-01;18:00:00;...;.;;...
1961-01-02;15:00:00;...;.  
..........;........;...;.
2015-09-01;........;...;.

使用以下命令(*)

awk -F ';' 'x==1 {print $1 " " $2 " " $3 " " $4} /Date/ {x=1}' file >> new_file

sed -i '' 's/[-:,]//g' new_file

创建new_file具有以下格式的

19610101   060000  0.4  G 
19610101   120000  2.3  G 
19610101   180000  ...  . 
19610102   150000  ...  .        
19610102   180000  ...  .       
19610103   060000  ...  .      
........   ......  ...  .
20150901   ......  ...  .

现在,使用命令 (**)

awk '
     {
        tspec = sprintf("%4d %.2d %.2d 00 00 00", substr($1,1,4), substr($2,1,2), substr($2,3,4))
        t = mktime(tspec)
        $(NF+1) = 0 + strftime("%j",t)
    } {print}' new_file

创建另一列并new_file包含天数。

19610101   060000  0.4  G 1
19610101   120000  2.3  G 1
19610101   180000  ...  . 1
19610102   150000  ...  . 2
19610102   180000  ...  . 2
19610103   060000  ...  . 3
........   ......  ...  . .
20150901   ......  ...  . .

有没有一种方法可以将命令 (*) 和 (**) 组合在一个脚本中?目前,这些是在两个单独的系统中运行的。

答案1

组合两个awk命令(以及sed):

awk -F ';' '
    x == 1 {
        gsub("[:,-]", "")
        tspec = sprintf("%4d %.2d %.2d 00 00 00", substr($1,1,4), substr($1,5,2), substr($1,7,4))
        t = mktime(tspec)
        print $1, $2, $3, $4, 0 + strftime("%j", t)
    }
    /Date/ { x = 1 }' file

这假设您使用的是 GNUawkmawk(不是 BSD awk,它可能不会实现mktime()strftime())。

该代码结合了两个awk命令和sed(使用gsub()),并且我还冒昧地纠正了设置日期的解析tspec

给定一个文件,

...
...
Date;Time;Airtemp;Quality;;Other info
1961-01-01;06:00:00;0.4;G;;...
1961-01-01;12:00:00;2.3;G;;...
1961-01-01;18:00:00;...;.;;...
1961-01-02;15:00:00;...;.
2015-09-01;........;...;.

这会产生

19610101 060000 0.4 G 1
19610101 120000 2.3 G 1
19610101 180000 ... . 1
19610102 150000 ... . 2
20150901 ........ ... . 244

请注意,空格是默认的输出字段分隔符 ( OFS),因此,如果您没有OFS明确设置任何内容,则您不必(不应该)必须" "在每个输出字段之间使用空格来输出。

答案2

这个问题很难回答,因为你没有向我们展示真实的数据。但是,如果我理解正确的话,您根本不需要考虑时间戳。根据您想要的输出,您只需从输入中删除-和并添加额外的列::

$ awk -F';' '{day=substr($1,9,2); gsub(/[:-]/,""); printf "%s;%.1d\n",$0,day}' file
19610101;060000;0.4;G;...;1
19610101;120000;2.3;G;...;1
19610101;180000;...;.;1
19610102;150000;...;.  ;2
..........;........;...;.;0
20150901;........;...;.;1

或者,如果您想要在所需输出中显示(我认为)的制表符分隔列:

 $ awk -F';' -vOFS="\t" '{day=substr($1,9,2); gsub(/[:-]/,""); print $1,$2,$3,$4, sprintf("%.1d",day)}' file
19610101    060000  0.4 G   1
19610101    120000  2.3 G   1
19610101    180000  ... .   1
19610102    150000  ... .   2
..........  ........    ... .   0
20150901    ........    ... .   1

答案3

尝试将 $4 更改为 $5 以显示一年中的某一天

{print $1 " " $2 " " $3 " " $4}

相关内容