![CSV 文件日期格式](https://linux22.com/image/121230/CSV%20%E6%96%87%E4%BB%B6%E6%97%A5%E6%9C%9F%E6%A0%BC%E5%BC%8F.png)
这是我的问题的简短版本:如何将逗号分隔的日期列表从一种格式转换为另一种格式?更具体地说,我想要一个单行命令来转换这种形式的字符串:
YYYY/MM/DD,YYYY/MM/DD
为以下形式的字符串:
DD/MM/YYYY,DD/MM/YYYY
现在我将描述我的问题的背景。
我有一个 CSV 文件,其行包含以下格式的相邻日期对:
YYYY/MM/DD
我运行以下grep
命令来提取这对日期:
grep -Po '[1-2][0-1][0-9][0-9]/[0-1][0-9]/[0-1][0-9]','[1-2][0-1][0-9][0-9]/[0-1][0-9]/[0-1][0-9]' file.csv`
例如,这会产生如下字符串:
2016/05/16,2017/06/15
我可以使用date
以下命令转换单个日期字符串:
date -d '2016/05/16' '+%d/%m/%Y'
这会产生所需的结果:
16/05/2016
我尝试将此命令应用于多个输入字符串,例如:
date -d"2016/05/16","2017/06/15" "+%d-%m-%Y"
但这没有用。我收到以下错误消息:
Error :- Invalid date - 2016/05/16,2017/06/15'
我想要的是一个将转换2016/05/16,2017/06/15
为16/05/2016,15/06/2017
.
答案1
使用 sed ...
echo "2016/05/16,2017/06/15" | sed 's/\([0-9]\{4\}\)\/\([0-9]\{2\}\)\/\([0-9]\{2\}\),\([0-9]\{4\}\)\/\([0-9]\{2\}\)\/\([0-9]\{2\}\)/\3\/\2\/\1,\6\/\5\/\4/g'
16/05/2016,15/06/2017
答案2
这是一个扩展您对该date -d
命令的使用的解决方案。它仅使用 shell 脚本和标准 GNU 命令行tr
工具paste
:
tr ',' '\n' \
| while read line; do date -d "${line}" "+%d/%m/%Y"; done \
| paste -d, -s -
我们使用tr
将逗号转换为换行符,将一行输入分成两行。然后,我们将这两行通过管道传送到一个while
循环,并将格式化命令应用date
到每行。最后,我们通过管道传输转换后的日期字符串,paste
以便将它们重新组合成单个逗号分隔的列表。
以下是示例输入的样子:
echo 2016/05/16,2017/06/15 \
| tr ',' '\n' \
| while read line; do date -d "${line}" "+%d/%m/%Y"; done \
| paste -d, -s -
这是它产生的输出:
16/05/2016,15/06/2017
将此与grep
您帖子中的命令相结合,我们得到以下结果:
grep -Po '[1-2][0-9][0-9][0-9]/[0-1][0-9]/[0-1][0-9]','[1-2][0-9][0-9][0-9]/[0-1][0-9]/[0-1][0-9]' file.csv \
| tr ',' '\n' \
| while read line; do date -d "${line}" "+%d/%m/%Y"; done \
| paste -d, -s -
您可能还想缩短与 一起使用的正则表达式grep
。也许这样的东西也可以工作(注意它与尾随逗号匹配):
grep -Po '([12][0-9]{3}(/[01][0-9]){2},?){2}' file.csv
最后,我们可以使用输出重定向将结果写入文件:
grep -Po '[1-2][0-9][0-9][0-9]/[0-1][0-9]/[0-1][0-9]','[1-2][0-9][0-9][0-9]/[0-1][0-9]/[0-1][0-9]' file.csv \
| tr ',' '\n' \
| while read line; do date -d "${line}" "+%d/%m/%Y"; done \
| paste -d, -s - \
> new_file.csv