2016-09-20 137 views
0

我使用一个外壳脚本来处理在下面的格式数据csv文件日期:外壳脚本解析

YYYY-MM-DD,值

每一行都有一个不同的日期和一个不同值。

我想每一行解析为以下新的格式:

YYYY,WEEKNUM,YYYY-MM-DD,价值

,其中yyyy是4位数的年份之日起上线,weeknum是该日,月和年的星期编号。

我已经制定了使用日期命令获取WEEKNUM,在那里我硬编码的日期到2016年2月1日为例:

echo $(date -j -f '%Y-%m-%d' '2016-02-01' '+%V') 

但我只是不知道如何将此日期命令合并到sed之类的地方,我可以根据文件中该行的实际日期值动态地将yyyy和weeknum值插入到每行中。

有关如何进行的任何建议将不胜感激!

沙龙

+1

你能提供一些样本输入,与你的目标的预期产出一起,这样我们就可以运行测试,并且相信他们是你正在寻找的结果? – ghoti

回答

2

这可能会做:

$ uname -sr 
Darwin 15.4.0 
$ cat inp 
2016-01-01, 5 
2016-01-09, 15 
2016-02-01, 3.14 
$ while IFS=", " read d v; do date -j -f '%Y-%m-%d' "$d" "+%Y, %V, %F, $v"; done < inp 
2016, 53, 2016-01-01, 5 
2016, 01, 2016-01-09, 15 
2016, 05, 2016-02-01, 3.14 

这一切持久性有机污染物进入了date命令的格式,避免了子shell或临时变量的需要。

请注意选择引号。虽然格式字符串通常被认为是静态的,并且通常放置在单引号中,但如果我们想要在格式中包含变量$v,则必须使用双引号,以允许进行变量扩展。请注意,如果由于某种原因,CSV中的输入数据“脏”,则可能会轻松中断处理,因为除了date解析第一个字段的能力之外,它不提供输入检查。


UPDATE

如果你要使用MacportsBrew,,那么你的系统上安装GNU AWK(GAWK)以下可能会表现得更好:

gawk 'BEGIN{OFS=FS=", "} {split($1,a,"-"); print a[1],strftime("%V",mktime(gensub(/-/," ","g",$1) " 00 00 00")),$1,$2}' inp 

我把它写成一行代码,但是为了更容易解释,我会打破这一点。

  • BEGIN { OFS=FS=", " } - 在脚本的开头,定义了一个字段分隔符。
  • { - 此awk脚本的主要部分没有“条件”,因此将针对每一行输入执行。
  • split($1,a,"-") - 将第一个字段拆分为数组a[],用连字符分隔。
  • print a[1], - 打印输出,从全年
  • strftime("%V", - 后跟年周的最时间格式,
  • mktime(gensub(/-/," ","g",$1) " 00 00 00")) - 从mktime的“datespec”格式解析的时候产生的,
  • ,$1,$2} - 之后是其他两个字段。

我还没有开发的任何性能指标,但我敢肯定的自包含gawk的选项将运行比对输入的每一行产生一个date命令基于bash的选项显著更快。

+0

没有'-r'的情况下读取会破坏反斜杠... –

+0

@ l'L'-OP描述的输入数据中没有反斜杠。 – ghoti

+0

@ l'L'I - 文件中的数据非常干净。我不必担心任何异常处理。 – SharonG