用于解析日期的Shell脚本

时间:2016-09-20 00:53:06

标签: bash shell date sed osx-yosemite

我正在使用shell脚本来处理包含以下格式的数据的csv文件:

yyyy-mm-dd,值

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

我想将每一行解析成以下新格式:

yyyy,weeknum,yyyy-mm-dd,value

yyyy是该行上日期的4位数年份,而weeknum是该日,月份和年份的周数。

我已经计算出使用date命令获取周期,我将日期硬编码为2016-02-01为例:

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

但是我还不确定如何将这个日期命令合并到像sed这样的地方,我可以根据文件中该行的实际日期值动态地全局地将yyyy和weeknum值插入到每一行中。

非常感谢任何有关如何进行的建议!

沙龙

1 个答案:

答案 0 :(得分: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中的输入数据是“#34;脏&#34;”,则可能会轻易破坏您的处理,因为除了date解析第一场。

<强>更新

如果您使用MacportsBrewetc在系统上安装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脚本的主要部分没有&#34; condition&#34;,因此将对每一行输入执行。
  • split($1,a,"-") - 将第一个字段拆分为数组a[],用连字符分隔。
  • print a[1], - 打印输出,从年份开始,
  • strftime("%V", - 后面是一周中的时间格式,
  • mktime(gensub(/-/," ","g",$1) " 00 00 00")) - 根据在mktime&#34; datepec&#34;中解析的时间生成格式,
  • ,$1,$2} - 其次是其他两个字段。

我还没有开发任何性能指标,但我确定自包含gawk选项的运行速度明显快于基于bash的选项,该选项会为每一行产生date命令。输入