我以前有一个类似以下的脚本
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
(。
您的第二个版本更好,因为:
- 它只需要在文件上进行一次传递(不需要像您想象的那样进行多次传递(
- 它没有globbing和spacing错误(您的第一次尝试对于
green beans
或/*/*/*/*
表现不佳(
当1时,完全在shell代码中读取文件是完全可以的。你做对了。开销可以忽略不计,但这两者都不适用于第一个示例(除了文件当前很小这一事实(。