尝试了很多 awk 和 sed 命令,但无法正确格式化文件。主要问题是处理有时存在而有时不存在的列中间的额外逗号。
这是它在 csv 文件中的样子:
Num,Type,StartTime,Duration,Var1,Var2,Var3
1,Forward,9/11/2019 11:15,"15 h, 45 m",98.03,-1.38,-0.2
2,Forward,9/12/2019 13:00,"8 h, 21 m",97.84,-0.83,1.27
3,Forward,9/12/2019 21:30,"20 h, 30 m",99.06,-2.12,-1.64
4,Forward,9/14/2019 8:00,18 h,97.47,-0.84,0.07
5,Backward,9/30/2019 14:00,56 m,95.93,-0.17,1.26
这就是它需要的样子:
Num,Type,StartTime,Duration,Var1,Var2,Var3
1,Forward,9/11/2019 11:15,15:45,98.03,-1.38,-0.2
2,Forward,9/12/2019 13:00,8:21,97.84,-0.83,1.27
3,Forward,9/12/2019 21:30,20:30,99.06,-2.12,-1.64
4,Forward,9/14/2019 8:00,18:00,97.47,-0.84,0.07
5,Backward,9/30/2019 14:00,0:56,95.93,-0.17,1.26
答案1
以下是如何确保您仅有的使用 awk 脚本修改所需字段
BEGIN { FPAT = "([^,]+)|(\"[^\"]+\")"; OFS = "," }
function convert_time(timestr)
{
gsub(/[" ]/, "", timestr);
if (timestr !~ ",") {
number = substr(timestr, 1, length(timestr) -1)
if (timestr ~ "m$") return "0:" number
if (timestr ~ "h$") return number ":00"
} else {
gsub(/[^0-9,]/,"", timestr)
gsub(/,/,":", timestr)
return timestr
}
}
NR > 1 { $4 = convert_time($4) }
{ print $0 }
- 通过使用FPAT即使某些字段包含逗号,您也可以拆分 awk 中的变量 - 只要它们嵌入双引号中。
- 我在用着欧福斯变量以确保当我打印修改后的行时,字段将以逗号分隔。
- 在每一行上(除了第一行,我假设它是标题),我使用
convert_time
我编写的函数根据请求转换第四个字段。 - 最后我打印修改后的行。
函数convert_time
:首先,我假设可能只有分钟和小时;例如,如果该字段还可能包含一天,则该函数将无法正常工作,需要进行相应修改。
- 我用来
gsub
从变量中删除任何空格或引号timestr
。 - 如果
timestr
不包含任何逗号,则表示只有一个项目 - 分钟或小时。- 我通过使用函数删除最后一个字符来仅获得数字
substr
。 - 如果变量的最后一个字符
timestr
是 m(分钟),则返回 00:number - 如果变量的最后一个字符
timestr
是 h(表示小时),则返回 number:00
- 我通过使用函数删除最后一个字符来仅获得数字
- 如果
timestr
包含逗号,我假设第一个数字是小时,第二个数字是分钟。- 我用来
gsub
删除任何不是数字或逗号的字符 - 这将删除 h 和 m 字符,并且仅保留数字和逗号。 - 然后我用冒号替换逗号(标点符号,而不是体内器官......),再次使用
gsub
.
- 我用来
我将整个脚本放入一个名为 的文件中convert_time.awk
,然后运行它。
输出:
$ cat file.csv | awk -f convert_time.awk
Num,Type,StartTime,Duration,Var1,Var2,Var3
1,Forward,9/11/2019 11:15,15:45,98.03,-1.38,-0.2
2,Forward,9/12/2019 13:00,8:21,97.84,-0.83,1.27
3,Forward,9/12/2019 21:30,20:30,99.06,-2.12,-1.64
4,Forward,9/14/2019 8:00,18:00,97.47,-0.84,0.07
5,Backward,9/30/2019 14:00,0:56,95.93,-0.17,1.26
请注意,在本例中,它仅修改了特定字段 - 第 4 个字段。
答案2
sed 's/"//g' kl| awk '!/m/{gsub("h,","h,00 m,",$0)}1'| sed "s/h,/:/g"| sed "s/m,/,/g"|sed -r "s/\s+:\s+/:/g"
输出
1,Forward,9/11/2019 11:15,15:45 ,98.03,-1.38,-0.2
2,Forward,9/12/2019 13:00,8:21 ,97.84,-0.83,1.27
3,Forward,9/12/2019 21:30,20:30 ,99.06,-2.12,-1.64
4,Forward,9/14/2019 8:00,18 :00 ,97.47,-0.84,0.07
5,Backward,9/30/2019 14:00,56 ,95.93,-0.17,1.26