bash编程中是否有写缓冲区?

时间:2013-05-29 15:39:49

标签: bash operating-system

bash编程中是否有写入文件缓冲区?如果有,可以改变它的大小。

这是问题

我有一个bash脚本,它逐行读取文件,然后操作读取数据,然后将结果写入另一个文件。像这样的东西

while read line 
  some grep, but and sed
  echo and append to another file

输入数据非常庞大(近20GB的文本文件)。进度很慢所以出现一个问题,如果bash的默认行为是将结果写入每个读取行的输出文件中,那么进度将会很慢。

所以我想知道,是否有任何机制来缓冲某些输出然后将该块写入文件?我在互联网上搜索了这个问题,但没有找到任何有用的信息...

是操作系统相关问题还是bash?操作系统是centos版本6.

脚本是

#!/bin/bash
BENCH=$1
grep "CPU  0" $BENCH > `pwd`/$BENCH.cpu0
grep -oP '(?<=<[vp]:0x)[0-9a-z]+' `pwd`/$BENCH.cpu0 | sed 'N;s/\n/ /' |  tr '[:lower:]' '[:upper:]' > `pwd`/$BENCH.cpu0.data.VP
echo "grep done"
while read line ; do
   w1=`echo $line | cut -d ' ' -f1`
   w11=`echo "ibase=16; $w1" | bc`
   w2=`echo $line | cut -d ' ' -f2`
   w22=`echo "ibase=16; $w2" | bc`
   echo $w11 $w22 >> `pwd`/$BENCH.cpu0.data.VP.decimal
done <"`pwd`/$BENCH.cpu0.data.VP"
echo "convertion done"

2 个答案:

答案 0 :(得分:5)

循环中的每个回显和追加都会打开和关闭文件,这可能会对性能产生负面影响。

一种可能更好的方法(你应该简介)只是:

grep 'foo' | sed 's/bar/baz' | [any other stream operations] <$input_file >$output_file 

如果您必须保留现有结构,那么另一种方法是创建named pipe

mkfifo buffer

然后创建2个进程:一个写入管道,另一个从管道读取。

#proc1
while read line <$input_file; do
    grep foo | sed 's/bar/baz' >buffer
done


#proc2
while read line <buffer; do
    echo line >>$output_file
done

实际上我希望瓶颈完全是文件IO,但这确实在读写之间创造了独立性,这可能是理想的。

如果你有20GB个RAM,它可能会提高使用内存映射临时文件而不是命名管道的性能。

答案 1 :(得分:2)

为了看看差异是什么,我创建了一个包含一堆

的文件
a somewhat long string followed by a number: 0000001

包含10,000行(约50MiB),然后通过shell读取循环

运行它
while read line ; do
  echo $line | grep '00$' | cut -d " " -f9 | sed 's/^00*//'
done < data > data.out

花了差不多6分钟。与等效的

相比
grep '00$' data | cut -d " " -f9 | sed 's/^00*//' > data.fast

花了0.2秒。为了消除分叉的成本,我测试了

while read line ; do
  :
done < data > data.null

其中:是内置的shell,根本不执行任何操作。正如预期的那样,data.null没有内容,循环仍需要21秒才能运行我的小文件。我想测试一个20GB的输入文件,但我不是那么耐心。

结论:了解如何使用awkperl,因为如果您尝试使用我在撰写本文时发布的脚本,您将永远等待。