考虑一堆几乎相同的 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
这假设您使用的是 GNUawk
或mawk
(不是 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}