更快地将Bash写入文件

4
我正在使用bash读取文件,在将值取出并保存到另一个文件中。 该文件有约十万行,读取和重写所有行需要大约25分钟。
也许有更快的方法来写入文件,因为现在我只是迭代遍历每一行,解析一些值并像这样保存它们:
while read line; do
   zip="$(echo "$line" | cut -c 1-8)"
   echo $zip
done < file_one.txt

一切都正常工作,值被正确解析,我只想知道如何优化这个过程(如果可能的话)。

谢谢。


1
当读取循环非常缓慢时 - 123
4个回答

5

循环会使程序变慢(特别是在每次迭代中调用外部程序(cut)的部分)。你可以在一次cut中完成所有操作:

cut -c 1-8 file_one.xt

这将打印每行的结果。我不确定原始代码中zip变量赋值的目的是什么。 - Petr Skocik
忘了提一下: 我使用循环是因为之后我还需要检查其他值。根据其内容,其他值将不得不被削减(我将不得不添加一个“if”)。 这是个好主意,但我不确定当我添加那个时是否真的能用它... - Luka
1
将此内容输入到您的 while 循环中。它会大大加快速度。Bash 循环很慢,但更慢的是每次迭代都调用可执行文件(这就是您现在正在做的事情)。 - Petr Skocik
请您能否进一步解释一下,我对此还比较陌生。 - Luka
启动外部可执行文件需要一些开销。将其乘以100K行,你就会得到很多开销。Bash循环也会为每次迭代增加开销,但不会太多。如果你只使用bash内置函数来获取前8个字符,它会更快(但仍然因为bash循环而慢)。使用一个cut命令是最好的选择。 - Petr Skocik
1
哦,我现在明白了 :) 非常感谢! - Luka

2

对于每一行都调用一次cut是一个很大的瓶颈。相反,使用子字符串扩展来获取每行的前8个字符。

while read line; do
   zip=${line:0:8}
   echo $zip
done < file_one.txt

1
如果您希望在满足某些条件的情况下对行的子字符串进行操作,则 Awk 专为操作文本文件而设计:
awk '{zip=substr($0, 1, 8)} zip == "my match" {print zip}' file_one.txt

在这个例子中,substr($0, 1, 8)表示file_one.txt每行记录($0)的第1到8个字符。这些子字符串被赋值给zip变量,并且只有在匹配文本"my match"时才会打印出来。
如果您不熟悉Awk,并且经常需要操作大文件,我建议您花些时间学习它。Awk比bash读取循环快得多,更有效率。博客文章 - 20分钟学会Awk - 是一个很好的、快速的介绍。
为了在大文件上进一步节省时间,您可以使用一个名为Mawk的优化版本的Awk。

1

我会选择这个,因为它只执行一次切割操作:

while read line; do
   echo $line
done < <(cut -c 1-8 file_one.txt)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接