5

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

这是问题

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

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

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

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

是操作系统相关的问题还是 bash?操作系统是centos release 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"
4

2 回答 2

5

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

一个可能更好的方法(你应该配置文件)很简单:

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

如果您必须保留现有结构,那么另一种方法是创建命名管道

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,则使用内存映射临时文件而不是命名管道可能会提高性能。

于 2013-05-29T15:44:50.720 回答
3

只是为了看看有什么不同,我创建了一个包含一堆

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

where:是一个内置的 shell,它什么都不做。正如预期的那样data.null,没有内容,循环仍然需要 21 秒才能运行我的小文件。我想测试一个 20GB 的输入文件,但我不是那么有耐心。

结论:学习如何使用awk,否则perl如果您尝试使用我写这篇文章时发布的脚本,您将永远等待。

于 2013-05-29T16:45:19.667 回答