Shell 解析日期的脚本
Shell Script to Parse Date
我正在使用 shell 脚本处理包含以下格式数据的 csv 文件:
yyyy-mm-dd,值
每一行都有不同的日期和不同的值。
我想将每一行解析为以下新格式:
yyyy,weeknum,yyyy-mm-dd,值
其中 yyyy 是从该行日期算起的 4 位数年份,weeknum 是该日、月和年的周数。
我已经使用 date 命令获取周数,例如我将日期硬编码为 2016-02-01:
echo $(date -j -f '%Y-%m-%d' '2016-02-01' '+%V')
但我只是不确定如何将此日期命令合并到 sed 之类的东西中,在那里我可以根据文件中该行的实际日期值动态和全局地将 yyyy 和 weeknum 值插入到每一行中。
如有任何关于如何进行的建议,我们将不胜感激!
莎伦
这可能会:
$ 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 中的输入数据是 "dirty",您可能会轻易中断处理,因为除了 date
解析第一个字段的能力之外,它不提供任何输入检查。
更新
如果您使用 Macports or Brew, etc 在您的系统上安装 GNU awk (gawk),那么以下可能会表现更好:
gawk 'BEGIN{OFS=FS=", "} {split(,a,"-"); print a[1],strftime("%V",mktime(gensub(/-/," ","g",) " 00 00 00")),,}' inp
我是单行本写的,但为了便于解释,我会打破入点。
BEGIN { OFS=FS=", " }
- 在脚本的开头,定义一个字段分隔符。
{
- 此 awk 脚本的主要部分没有 "condition",因此将针对每一行输入执行。
split(,a,"-")
- 将第一个字段拆分为数组 a[]
,以连字符分隔。
print a[1],
- 打印输出,从年份开始,
strftime("%V",
- 后跟一年中一周的时间格式,
mktime(gensub(/-/," ","g",) " 00 00 00"))
- 从以 mktime 的 "datespec" 格式解析的时间生成,
,,}
- 后跟其他两个字段。
我还没有制定任何性能指标,但我确信独立的 gawk 选项 运行 比产生 [=12= 的基于 bash 的选项快得多] 每行输入的命令。
我正在使用 shell 脚本处理包含以下格式数据的 csv 文件:
yyyy-mm-dd,值
每一行都有不同的日期和不同的值。
我想将每一行解析为以下新格式:
yyyy,weeknum,yyyy-mm-dd,值
其中 yyyy 是从该行日期算起的 4 位数年份,weeknum 是该日、月和年的周数。
我已经使用 date 命令获取周数,例如我将日期硬编码为 2016-02-01:
echo $(date -j -f '%Y-%m-%d' '2016-02-01' '+%V')
但我只是不确定如何将此日期命令合并到 sed 之类的东西中,在那里我可以根据文件中该行的实际日期值动态和全局地将 yyyy 和 weeknum 值插入到每一行中。
如有任何关于如何进行的建议,我们将不胜感激!
莎伦
这可能会:
$ 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 中的输入数据是 "dirty",您可能会轻易中断处理,因为除了 date
解析第一个字段的能力之外,它不提供任何输入检查。
更新
如果您使用 Macports or Brew, etc 在您的系统上安装 GNU awk (gawk),那么以下可能会表现更好:
gawk 'BEGIN{OFS=FS=", "} {split(,a,"-"); print a[1],strftime("%V",mktime(gensub(/-/," ","g",) " 00 00 00")),,}' inp
我是单行本写的,但为了便于解释,我会打破入点。
BEGIN { OFS=FS=", " }
- 在脚本的开头,定义一个字段分隔符。{
- 此 awk 脚本的主要部分没有 "condition",因此将针对每一行输入执行。split(,a,"-")
- 将第一个字段拆分为数组a[]
,以连字符分隔。print a[1],
- 打印输出,从年份开始,strftime("%V",
- 后跟一年中一周的时间格式,mktime(gensub(/-/," ","g",) " 00 00 00"))
- 从以 mktime 的 "datespec" 格式解析的时间生成,,,}
- 后跟其他两个字段。
我还没有制定任何性能指标,但我确信独立的 gawk 选项 运行 比产生 [=12= 的基于 bash 的选项快得多] 每行输入的命令。