我目前正在尝试使用grep
命令在一个非常大的id列表(约5000个)中对比一个更大的csv文件(300万行)。
我想要找到所有包含来自id文件的id的csv行。
我的天真做法是:
cat the_ids.txt | while read line
do
cat huge.csv | grep $line >> output_file
done
但这需要太长时间了!
是否有更高效的方法来解决这个问题?
我目前正在尝试使用grep
命令在一个非常大的id列表(约5000个)中对比一个更大的csv文件(300万行)。
我想要找到所有包含来自id文件的id的csv行。
我的天真做法是:
cat the_ids.txt | while read line
do
cat huge.csv | grep $line >> output_file
done
但这需要太长时间了!
是否有更高效的方法来解决这个问题?
grep -f the_ids.txt huge.csv
此外,由于您的模式似乎是固定字符串,提供-F
选项可能会加快grep
的速度。
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by
newlines, any of which is to be matched. (-F is specified by
POSIX.)
可以使用grep -f
来实现:
grep -f the_ids.txt huge.csv > output_file
根据 man grep
:
-f FILE, --file=FILE
从文件中获取模式,每行一个。空文件不包含任何模式,因此不匹配任何内容。(-f 由 POSIX 规范定义。)
如果您提供一些示例输入,则我们甚至可以更进一步改善 grep
条件。
$ cat ids
11
23
55
$ cat huge.csv
hello this is 11 but
nothing else here
and here 23
bye
$ grep -f ids huge.csv
hello this is 11 but
and here 23
grep -f filter.txt data.txt
在filter.txt
超过几千行时变得难以管理,因此不是这种情况下的最佳选择。 即使使用grep -f
,我们仍需要记住以下几点:
-x
选项-F
-x
选项,则使用-w
防止部分匹配这篇文章对这个主题进行了很好的讨论(在大型文件上使用grep -f
):
这篇文章谈到了grep -vf
:
grep -f
的最佳方法是:awk 'FNR==NR {hash[$0]; next} $0 in hash' filter.txt data.txt > matching.txt
在第二个文件中匹配特定字段(以“,”分隔符和该示例中的第2个字段为例):
awk -F, 'FNR==NR {hash[$1]; next} $2 in hash' filter.txt data.txt > matching.txt
对于grep -vf
:
匹配整行:
awk 'FNR==NR {hash[$0]; next} !($0 in hash)' filter.txt data.txt > not_matching.txt
在第二个文件中匹配特定字段(以“,”分隔符和本例中的第2个字段为例):
awk -F, 'FNR==NR {hash[$0]; next} !($2 in hash)' filter.txt data.txt > not_matching.txt
如果你使用ugrep来匹配the_ids.txt
中的字符串和你的大型huge.csv
文件,你可能会获得显著的搜索加速:
ugrep -F -f the_ids.txt huge.csv
这对 GNU grep 也有效,但我期望 ugrep 运行速度能快几倍。