删除所有行中的字母和点

删除所有行中的字母和点

我有一个 CSV,其中包含不同程序的命令的输出,time包括执行的 ID。

因此我的文件包含以下形式的记录:

ID,execution_time

示例记录:

345,0m0.047s

我只需要执行次数和秒数。

因此,上述记录需要

345,0047(没有“0m”,“。”和“s”)。

有可能实现吗?

答案1

如果有分钟怎么办?下面是将其转换为秒的方法:

awk -F'[m,]' '{print $1 "," $2*60 + $3}' file.csv

还有一些演示:

$ ... <(echo -e "345,0m0.047s\n345,1m0.047s\n345,1m2.047s")
345,0.047
345,60.047
345,62.047

我不确定你为什么要删除小数点,但你可以传递输出,sed 's/\.//g'如果你真的需要:

$ ... <(echo -e "345,0m0.047s\n345,1m0.047s\n345,1m2.047s") | sed 's/\.//g'
345,0047
345,60047
345,62047

呃。


假设这是一个time输出,如果值包含小时甚至天怎么办?我尝试了一下,想出了这个小妙招:

awk -F'[dhms,]' 'BEGIN{split("1 60 3600 86400", T, " ")}{t=0; for (i=NF-1; i>1; i--) t+=T[NF-i]*$i; printf("%s,%.3f\n", $1, t)}'

这将处理以下格式:*s *m*s *h*m*s*d*h*m*s并将它们全部转换为秒(保留三位小数)。强制性演示时间:

$ ... <(echo -e "345,1.2s\n345,12m5s\n345,1h2m5s\n345,1d2h1m2.047s")
345,1.200
345,725.000
345,3725.000
345,93662.047

答案2

以下是我的解决方案:

sed -i 's/[0-9]*m\|s\|\.//g' file.csv

您可能想要跳过第一行,如果它包含标题,如下所示:

sed -i '2,$s/[0-9]*m\|s\|\.//g' file.csv

请注意,该-i选项会导致sed“就地”工作,从而改变原始文件。如果您想创建一个新文件,请使用以下命令:

sed 's/[0-9]*m\|s\|\.//g' file.csv > new_file.csv

答案3

它应该是:

sed 's/m0\.\(.*\)s$/\1/g'

答案4

@kraxor 的答案是sed删除行中的“其他所有内容”,然后只显示该行。

但实际上“其他一切”? 至少从一行样本中我们能得出一个想法。但是当我们得到 CSV 标题行时该怎么办?要删除什么?
一般来说,我们不知道。

因此,实际上显示我们想要显示的数据

echo '345,0m0.047s' | sed -n -r 's/^(.*),.*[^0-9]([0-9]*)\.(.*)s$/\1,\2\3/p'

345,0047

到目前为止有效!

它有什么作用?
我们通常不打印该行(-n
(并激活更好的“扩展正则表达式”(-r))现在查找 ID、秒和秒的小数部分,
如果找到它们,则以正确的格式(添加“,”)将它们放入行中,
然后打印新创建的行。

现在一些其他输入,很正常,有两行数据:

ID,execution_time
123, Oops a comment0m0.0333s
345,0m0.047s

嗯?!看起来真实世界数据, 实际上!

echo "ID,execution_time\n123, Oops a comment0m0.0333s\n345,0m0.047s" | sed -r -n 's/^(.*),.*[^0-9]([0-9]*)\.(.*)s$/\1,\2\3/p'

123,00333
345,0047

看上去很漂亮,正好!



为了证明这样做有一定优点,我将与之前的答案进行比较:

echo "ID,execution_time\n123, Oops a comment0m0.0333s\n345,0m0.047s" | sed 's/[0-9]*m\|s\|\.//g'

ID,execution_tie
123, Oop a coent00333
345,0047

好的,实际的、干净的数据线顺利通过了;
但其他部分,情况就不怎么样了(注意,标题不只是通过了,而且被切断了)。

(请注意,有一个解决方案可以明确跳过标题行(或者可能是第一个数据行,我们知道吗?))

相关内容