我有这个 grep 命令来查找具有匹配模式的文件。
grep -oiE 'pattern1|pattern2|pattern3|pattern4' *pattern_in_a_filename* | sort -u
输出:
file_one:pattern1
file_two:pattern2
file_two:pattern3
我想要的是输出pattern4
未找到的说法,如下例所示:
file_one:pattern1
file_two:pattern2
file_two:pattern3
pattern4 not found
我正在制作成千上万的图案,并且必须尽快完成,因为这些是我们运营中所需的关键数据。
答案1
它必须这样做快的尽可能
想要尽快完成事情吗?
发现并行处理并应用以下 GNUparallel
解决方案:
正确的方法是从将所有模式放入文件开始,比方说patterns.txt
。
关键工作:
cat patterns.txt | parallel -j 0 --no-notice 'grep -Hoi {} /path/to/files/* || echo "{} not found"' | sort -u
-j N
- 职位数量。并行运行N
作业。0
意思是尽可能多。默认值为 100%,即每个 CPU 核心运行一个作业。
上述命令将搜索每个图案从patterns.txt
所有文件中并行。
我做了一个测试,只有2CPU 核心,包含一些模式列表和一些每个 641 Mb 的 csv 文件。我有大约470%与连续处理相比,时间速度有所提高。
您的计算机拥有的 CPU 核心越多,您达到的速度性能就越快。
得出你的结论...
答案2
该工具grep
按模式搜索文件。这意味着模式是输入,文件是输出。这意味着您可以使用 grep 找到的只是文件,而不是模式。
为了找到那些不包含匹配模式的文件,您必须使用-v
.这需要两次调用。
例子:
$ echo a > xa
$ echo ab > xab
$ echo c > xc
$ { grep -oiE 'a|b' x*; grep -vl -E 'a|b' x*; } | sort -u
xa:a
xab:a
xab:b
xc
为了找到那些不匹配的模式,您必须将模式作为输入,将搜索结果作为模式。匹配列表成为模式,模式成为您必须在其中进行搜索的数据。
我们假设这可能是前面示例中的文件的模式。
$ pattern='a|b|d'
然后将匹配模式列表存储在数组中:
$ found=($(grep -hoiE "$pattern" x* | sort -u))
这会将数组转换为新模式:
$ new_pattern="$(IFS='|' ; echo "${found[*]}")"
这会将原始模式转换为数据:
$ data="${pattern//|/$'\n'}"
这是不匹配的模式列表:
$ grep -viE "$new_pattern" <<< "$data"
d
答案3
这是实现您期望的方法。既然你说你有数千种模式,所以我假设你喂养图案从文件中获取,那么这比直接传递要好得多图案到grep
。命令如下。
grep -oif ../patt_file file* &&
printf "%s Not Found.\n" $(grep -vFxf <(grep -oihf ../patt_file file*) \
<(< ../patt_file))
为了避免匹配图案文件patt_file
本身,您需要将其移动到与输入infiles*
所在的目录不同的目录。
答案4
这是一个sh
生成您需要的结果的脚本。
#!/bin/sh
grep -f /path/to/patterns.txt /path/to/*_856_2017* | sort -u > /path/to/foundFiles.txt
while read -r LINE
do
grep -F "$LINE" /path/to/foundFiles.txt
if [ $? -eq 1 ]
then
echo "$LINE" not found
fi
done < /path/to/patterns.txt
在此脚本中,我假设您输出的结果你的 grep
到文件found.txt
,并且将模式存储在文件中/path/to/foundFiles.txt
。
正如您所看到的,grep
in 循环将生成文件的相同内容,found.txt
同时添加"$pattern" not found
丢失的内容。
我还为您的案例设计了第二种方法:
#!/bin/sh
grep -f /path/to/patterns.txt /path/to/*_856_2017* |
sort -u > /path/to/foundFiles.txt
comm -23 /path/to/patterns.txt /path/to/foundFiles.txt |
xargs -L 1 -I {} echo {} not found > /path/to/notFoundFiles.txt
cat /path/to/foundFiles.txt /path/to/notFoundFiles.txt > /path/to/finalList.txt
在这种情况下,patterns.txt
需要已经排序才能comm
工作。
该comm
命令比较两个文件,返回仅在patterns.txt
(-23
参数) 中出现的行,这是 未找到的模式列表grep
。
然后,xargs
抓取每一行 ( -L 1
) 并回显该行 ( {}
) 并附加“未找到”。结果xargs
被重定向到notFoundFiles.txt
文件。
最后,您只需将 findFiles.txt 和 notFoundFiles.txt 连接到finalList.txt
.