计算列性能问题

时间:2018-05-29 14:10:47

标签: shell awk

我有一个包含130,000行的.csv文件。我想读取此文件中的所有行并检查列数是否小于17,然后在行尾添加|0

首先我计算了列数,但只有这样,运行时间从10秒增加到近3分钟。

这是我尝试过的:

while read line;
do
    nr_columns=$(echo $line | awk -F'|' '{print NF}')
    echo $line>> out
done<input_file.csv

我也尝试使用tr,但运行时间也有所增加。

我怎样才能更快地完成这项工作?

谢谢大家。这就是我所做的:

awk -v separator=$sep -v nr_fields=$header_col -F '$sep' '{ if (NF  < nr_fields) print $0separator0;else print $0}' input_file.csv > outputfile

4 个答案:

答案 0 :(得分:2)

通过识别awk不仅仅适用于单行,您可以更快地完成它 - 它是一种真正的编程语言。将其放在文件foo.awk

BEGIN {
    OFS="|"
}
NF < 17 {
    print $0,"0"
}
NF >= 17 {
    print
}

然后像awk -F'|' -f foo.awk input_file.csv一样运行。

答案 1 :(得分:1)

听起来你只需要:

awk -F'|' '{print $0 (NF<17 ? FS 0 : "")}' input_file.csv

但如果没有简洁,可测试的样本输入和预期输出,那只是猜测。

答案 2 :(得分:0)

不确定这是否是您要找的,但这绝对有效。

#!/bin/bash

if [ ! $(head -1 input_file.csv | awk -F'|' '{print NF}') -eq 17 ]; then
  echo "input_file.csv does not have 17 columns"
  exit 2
fi

sed 's/$/\|0/g' input_file.csv > out

首先,我们检查列数是否确实为17.如果不是,我们发送消息并退出。如果我们处于良好状态,我们会继续将|0添加到行中。

答案 3 :(得分:0)

除非你真的说“如果一个记录少于17个字段,我知道它有16个字段”,那么我会添加许多新字段到17:

awk 'BEGIN {FS=OFS="|"} NF < 17 {for (i=NF+1; i<=17; i++) $i=0} 1' <<END
1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17
1|2|3|4|5|6|7|8|9|10|11|12|13|14
a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q
END
1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17
1|2|3|4|5|6|7|8|9|10|11|12|13|14|0|0|0
a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q

你的方法如此缓慢的一些原因:

  1. bash很慢
  2. bash read命令非常慢:它一次读取一个字节
  3. 每行调用一次awk