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"
答案 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的输入文件,但我不是那么耐心。
结论:了解如何使用awk
或perl
,因为如果您尝试使用我在撰写本文时发布的脚本,您将永远等待。