awk 或 sed 格式化可变持续时间

awk 或 sed 格式化可变持续时间

尝试了很多 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

相关内容