在用于 for 循环(用于 greping 文件)和 greping 文件与使用文件查询之间,有什么更快/更好的做法?



我以前有一个类似以下的脚本

for i in $(cat list.txt)
do
grep $i sales.txt
done

其中cat list.txt

tomatoes
peppers
onions

cat sales.txt

Price Products
$8.88 bread
$6.75 tomatoes
$3.34 fish
$5.57 peppers
$0.95 beans
$4.56 onions

我是BASH/SHELL的初学者,在阅读了诸如"为什么使用SHELL循环处理文本被认为是糟糕的做法?"?我将以前的脚本更改为以下内容:

grep -f list.txt sales.txt

最后一种方法真的比使用for循环更好吗?起初我以为是这样,但后来我意识到这可能是一样的,因为grep每次在目标文件中grep不同的行时都必须读取查询文件。有人知道它是否真的更好吗?为什么?如果它更好的话,我可能会错过grep如何处理这项任务的一些内容,但我无法弄清楚。

扩展我的评论。。。

您可以通过git下载grep的源代码:

git clone https://git.savannah.gnu.org/git/grep.git

您可以在src/grep.c的第96行看到一条注释:

/* A list of lineno,filename pairs corresponding to -f FILENAME
arguments. Since we store the concatenation of all patterns in
a single array, KEYS, be they from the command line via "-e PAT"
or read from one or more -f-specified FILENAMES.  Given this
invocation, grep -f <(seq 5) -f <(seq 2) -f <(seq 3) FILE, there
will be three entries in LF_PAIR: {1, x} {6, y} {8, z}, where
x, y and z are just place-holders for shell-generated names.  */

这几乎是我们需要看到的所有线索,即被搜索的模式——无论是通过-e还是通过带有文件的-f——都被转储到数组中。这个数组就是搜索的来源。在C中遍历该数组将比shell遍历文件更快。因此,仅凭这一点就能赢得速度赛。

此外,正如我在评论中提到的,grep -f list.txt sales.txt更易于阅读,更易于维护,并且只需要调用一个程序(grep(。

您的第二个版本更好,因为:

  1. 它只需要在文件上进行一次传递(不需要像您想象的那样进行多次传递(
  2. 它没有globbing和spacing错误(您的第一次尝试对于green beans/*/*/*/*表现不佳(

当1时,完全在shell代码中读取文件是完全可以的。你做对了。开销可以忽略不计,但这两者都不适用于第一个示例(除了文件当前很小这一事实(。

最新更新