使用sed和date在文本文件(.csv)中重新格式化日期

时间:2017-10-17 03:26:35

标签: shell datetime awk sed command-line

这是输入.csv文件

"item1","10/11/2017 2:10pm",1,2, ...
"item2","10/12/2017 3:10pm",3,4, ...
.
.
.

现在,我想将第二列(日期)转换为此特定格式 date -d '10/12/2017 2:10pm' +'%Y/%m/%d %H:%M:%S',以便" 10/12/2017 2:10 pm" 转换为" 2017/10/12 14:10:00&# 34;

期待输出文件

"item1","2017/10/11 14:10:00",1,2, ...
"item2","2017/10/12 15:10:00",3,4, ...
.
.
.

我知道可以使用bash或python来完成,但我想在单行命令中完成。有任何想法吗?有没有办法将date结果传递给sed

3 个答案:

答案 0 :(得分:3)

单行awk方法。

awk -F',' '{gsub(/"/,"",$2); cmd="date -d\""$2"\" +\\\"%Y/%m/%d\\ %T\\\"";
    cmd |getline $2; close(cmd) }1' OFS=, infile #>>outfile
"item1","2017/10/11 14:10:00",1,2, ...
"item2","2017/10/12 15:10:00",3,4, ...

这将输出终端中的更改,如果需要记录输出,则需要将输出重定向到文件,或使用FILENAME将输出重定向到输入infile本身。

awk -F',' '{gsub(/"/,"",$2); cmd="date -d\""$2"\" +\\\"%Y/%m/%d\\ %T\\\"";
    cmd |getline $2; close(cmd); print >FILENAME }' OFS=, infile

或者GNU awk实现支持-i inplace标识符进行就地替换。见'awk' save modifications in place

答案 1 :(得分:1)

你可以在一行中完成,但这引出了一个问题 - “你想要多长时间?”由于你标记为'shell'而不是bash等,因此你的字符串处理有点受限。 POSIX shell提供了足够的功能来执行您想要的操作,但它并不是最快速的补救措施。您最终会得到一个调用awk的{​​{1}}或sed解决方案或一个调用dateawk来解析旧日期的shell解决方案原始文件并将结果提供给sed以获取您的新日期。你必须找出最有效的补救办法。

就单行而言,您可以执行与以下类似的操作,同时保持POSIX兼容。它只是使用date从文件中获取第二个awk,将结果传递给field循环,该循环使用while来获取长度并在{{1}内使用从原始日期expr length "$field"的末尾删除双引号,然后expr substr "$field" "2" <length expression - 2>获取olddt,最后date -d "$olddt" +'%Y/%m/%d %H:%M:%S'执行替换。你的单行(为了便于阅读,显示了自动续行)

newdt

示例输入文件

sed -i "s;$olddt;$newdt;"

生成的文件

$ awk -F, '{print $2}' timefile.txt | 
while read -r field; do 
olddt="$(expr substr "$field" "2" "$(($(expr length "$field") - 2))")"; 
newdt=$(date -d "$olddt" +'%Y/%m/%d %H:%M:%S'); 
sed -i "s;$olddt;$newdt;" timefile.txt; done

可能有更快的方法,但这是一个合理的长度单行(相对而言)。

答案 2 :(得分:0)

修改不那么丑陋的sed方法:

sed 's/^.*,"\|",.*//g;h;s#.*#date "+%Y/%m/%d %T" -d "&"#e;H;g;s#\n\|$#,#g;s/^/s,/' input.csv | sed -f - input.csv 

展开,(它的工作方式相同):

sed 's/^.*,"\|",.*//g
     h;
     s#.*#date "+%Y/%m/%d %T" -d "&"#e;
     H;
     g;
     s#\n\|$#,#g;
     s/^/s,/' input.csv | sed -f - input.csv 

输出:

"item1","2017/10/11 14:10:00",1,2, ...
"item2","2017/10/12 15:10:00",3,4, ...

工作原理:

第一个sed数据块使用 e 评估命令运行date,其输出为用于生成一些新的sed s ubstitute 命令。要显示新的 s 命令,请使用|评论临时替换shell脚本#管道:

s,10/11/2017 2:10pm,2017/10/11 14:10:00,
s,10/12/2017 3:10pm,2017/10/12 15:10:00,

这些是通过管道输送到第二个sed