如何将 grep 与文件中的正则表达式和模式一起使用?



>假设有一个文件包含很多模式

.com
.re
.net
...

并且有一个文件包含大量数据

www.recent
www.remix3d.com
www.verisign.net

我想要的结果是

www.remix3d.com
www.verisign.net

我使用命令grep -f pattern_file data_file,但结果是这样的

www.recent
www.remix3d.com
www.verisign.net

由于.rewww'.re'cent相匹配

如何指定文件中的模式可以与常规正则表达式一起使用?例如,我grep数据"以"特定模式结尾,并且模式来自模式文件。

模式文件必须包含模式(即具有正确转义的特殊字符(,我建议像这样修改您的模式文件:

.com$
.ru$
.net$

如果不想更改模式文件,则必须在外部执行转义。看看这个。

> cat pattern
.com
.re
.net
> cat pattern_data
www.recent
www.remix3d.com
www.verisign.net
> grep $(sed 's/$/$/g;s/^/\/g' pattern | tr 'n' '|' | sed 's/.$//g;s/|/\|/g') pattern_data
www.remix3d.com
www.verisign.net
>

请注意,已有用于对域名进行这种匹配的工具,用于处理公共后缀列表。 有许多库可用于处理它,其中一些经过了大量优化,如果后缀列表很大,则比处理正则表达式列表快得多。

听起来你的标准实际上是:

  • 模式文件实际上是一个字符串列表,而不是正则表达式列表(其中点 (.( 匹配任何单个字符(,
  • 这些模式旨在仅在字符串的 ENDS 处匹配(因此模式文件中每行的末尾都有一个隐式$(。

要满足第一个条件,您可以使用 grp 的-F选项:

$ grep -F -f pattern_file data_file

但这对嵌入其中一条线中间的.re没有帮助。如果可以修改模式文件,请将行更改为如下所示:

.com$
.re$
.net$

会将它们变成您想要的正则表达式。否则,您可能必须使用某些内容来解析该模式文件,以便创建所需的正则表达式。例如,使用 bash 数组和一些参数扩展:

$ mapfile -t a < pattern_file
$ declare -p a
declare -a a=([0]=".com" [1]=".re" [2]=".net")
$ printf -v new_re '|%s' "${a[@]}"
$ new_re="${new_re//./\.}"         # escape dots within regex
$ new_re="(${new_re:1})$"          # strip leading or-bar
$ echo "$new_re"
(.com|.re|.net)$
$ grep -E "$new_re" data_file
www.remix3d.com
www.verisign.net

或者,如果您不介意依靠另一个工具来减少行数:

$ grep -f <(sed 's/./\./g;s/$/$/' pat) file
www.remix3d.com
www.verisign.net

您可以将grep -f与进程中的sed替换一起使用,该替换将pattern_file中的每个扩展转换为正确的正则表达式:

grep -f <(sed 's/.*/\&$/' pattern_file) data_file

www.remix3d.com
www.verisign.net

sed命令的输出为:

sed 's/.*/\&$/' pattern_file

.com$
.re$
.net$

最新更新