![Bash 使用 awk 或其他 Linux 工具 (csvcut) 转换 csv 文件中的日期](https://linux22.com/image/105468/Bash%20%E4%BD%BF%E7%94%A8%20awk%20%E6%88%96%E5%85%B6%E4%BB%96%20Linux%20%E5%B7%A5%E5%85%B7%20(csvcut)%20%E8%BD%AC%E6%8D%A2%20csv%20%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E6%97%A5%E6%9C%9F.png)
awk -F"," '{OFS=","; $1=system("date -d "$1" +%d-%m-%Y") ; print $0}' data.csv | head
我正在尝试获取 csv 文件的第一列并将日期格式标准化为 %dd-%mm-%yyyy。
当我尝试上面的代码时,我得到日期:写入错误:管道损坏。
但是当我尝试下面的代码时:
dd=$(csvcut -c 1 -e ISO-8859-1 -d "," data.csv | head -2 | sed -n 2p)
echo $dd
echo $(date -d $dd "+%d-%m-%Y")
我得到输出:
2017-02-03
2017年3月2日
我究竟做错了什么。有什么提示吗?谢谢。
我的系统:Ubuntu 16.04.1 LTS
编辑2:这是一个示例文件:http://grn.dk/sites/default/files/attachments/data.csv
编辑:
确定 CSV 数据文件(输入):data.csv(有多行)
Bogført,Tekst,Beløb,Saldo
2017-02-03, random text,-425,-611524.54
输出:
Bogført,Tekst,Beløb,Saldo
03-02-2017, random text,-425,-611524.54
但日期格式可以是任何其他格式。我目前正在研究标准化 csv 导入作业的日期。谢谢。
答案1
system()
您以错误的方式使用该功能。或者更确切地说,这不是此处使用的内容,因为它不返回命令的输出,仅返回退出状态(输出发送到终端)。
假设date
是 GNU date
,这是一个awk
将执行日期重新格式化的脚本:
BEGIN { OFS = FS = "," }
$1 {
cmd = sprintf("date -d '%s' '+%%d-%%m-%%Y' 2>/dev/null", $1);
cmd | getline $1;
print;
close(cmd);
}
运行它:
$ awk -f script.awk data.csv
Bogført,Tekst,Beløb,Saldo
03-02-2017, random text,-425,-611524.54
该脚本将丢弃空输入行。它创建一个命令字符串cmd
,使用 GNU 进行实际的日期转换date
。来自的错误date
将被丢弃(并将$1
保持不变)。
要做到这一点cvssql
(来自csvkit
):
$ sed '1,2d' data.csv | csvsql -H --query 'SELECT strftime("%d-%m-%Y", a), b, c, d FROM stdin' | sed '1d' >new_data.csv
中的数据new_data.csv
将没有标题行。要将其添加回来:
$ cat <( head -n 1 data.csv ) new_data.csv >even_newer_data.csv
答案2
由于您使用的是 Ubuntu,因此您可能拥有 GNU awk
,它提供了有用的时间和日期函数:
echo "2017-03-02" | \
awk '{ gsub(/-/, " ", $1); t = mktime($1 " 0 0 0"); print strftime("%d-%m-%Y", t);}'
答案3
bash-4.1$ cat a.txt
2017-02-03, random text,-425,-611524.54
2017-02-08, random text,-425,-611524.54
2017-02-07, random text,-425,-611524.54
bash-4.1$ awk -F, '{a="date -d "$1" +%Y%m%d"; while (a |getline line){$1=line;}print $0}' OFS=, a.txt
20170203, random text,-425,-611524.54
20170208, random text,-425,-611524.54
20170207, random text,-425,-611524.54
bash-4.1$ awk -F, '{a="date -d "$1" +%Y%m"; while (a |getline line){$1=line;}print $0}' OFS=, a.txt
201702, random text,-425,-611524.54
201702, random text,-425,-611524.54
201702, random text,-425,-611524.54
awk -F, 'NR==1{print;next}{a="date -d "$1" +%Y%m"; while (a |getline line){$1=line;}print $0}' OFS=, a.txt