Bash while loop + cut slow

时间:2015-02-24 13:04:59

标签: bash cut

我正在尝试使用bash循环处理文件(1.5GB)来迭代每一行。我使用cut来简化(相对),最后得到:

while read line
do
    echo "$(echo $line | cut -d' ' -f 2-3)" "$(echo $line | cut -d'"' -f 20)"
done < TEST.log > IDS.log

这非常慢,只有大约2KB /秒。我需要更快的速度运行。

此外,这里的瓶颈是什么?

3 个答案:

答案 0 :(得分:4)

瓶颈可能是您为每行数据生成多个进程。至于替换,这个awk应该是等价的:

awk '{ split($0, a, "\""); print $2, $3, a[20] }' TEST.log > IDS.log

答案 1 :(得分:4)

Perl通常非常快:

perl -nE 'say join " ", (split " ")[1,2], (split /"/)[19]' TEST.log > IDS.log

Perl数组从0开始编制索引。

答案 2 :(得分:0)

这里最大的瓶颈是分解管道的子流程。只需消除命令替换和管道,即可获得显着的性能提升(参见:数量级)。

while IFS=$'\x01' read -r ss1 ss2 ss3 _ <&3 && \
      IFS='"' read -r -a quote_separated_fields; do
    printf '%s\n' "${ss2} ${ss3} ${quote_separated_fields[20]}"
done < TEST.log 3< <(tr ' ' $'\x01' <TEST.log) > IDS.log

这是如何工作的?

  • tr ' ' $'\x01'将输入中的空格更改为低ASCII字符,以避免特殊情况的处理(其中read会将空白行合并为单个字符)。将其放在3< <(...)之后将此操作的输出放在文件描述符#3上。
  • IFS=$'\x01' read -r ss1 ss2 ss3 _ <&3在这些字符上分割一行,将第一个字段放入ss1(我们不在乎),第二个字段放入ss2,第三个字段放入{{1 }},并将该行的其余部分插入ss3_导致此行从文件描述符3读取。
  • <&3将标准输入(FD 0)上IFS='"' read -r -a quote_separated_fields个字符的输入拆分为一个名为"的数组。