【问题标题】:How to use grep with regex and patterns from a file together?如何将 grep 与文件中的正则表达式和模式一起使用?
【发布时间】:2018-09-28 09:13:19
【问题描述】:

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

.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

由于.re 匹配www'.re'cent

如何指定文件中的模式可以与通用正则表达式一起使用?比如我 grep 数据“以”特定模式结束,模式来自模式文件。

【问题讨论】:

  • 文件中有很多模式,但您只想过滤以.com结尾的模式?
  • 确保使用与您的正则表达式语法匹配的正确 grep(pgrepegrepgrep),并确保使用 ^$ 锚当您想要在字符串的特定部分进行匹配时。
  • 什么是结果以及为什么它与您的预期输出不匹配?
  • @anubhava 嗨,我现在添加了结果和原因。

标签: regex linux grep


【解决方案1】:

模式文件必须包含模式(即具有正确转义的特殊字符),我建议修改你的模式文件如下:

\.com$
\.ru$
\.net$

【讨论】:

    【解决方案2】:

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

    > 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
    >
    

    【讨论】:

      【解决方案3】:

      请注意,已有用于此类域名匹配的工具,用于处理public suffix list。有许多libraries 可用于处理它,其中一些经过高度优化,如果后缀列表很大,将比处理正则表达式列表快得多。

      【讨论】:

        【解决方案4】:

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

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

        要满足第一个条件,可以使用 grep 的 -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
        

        【讨论】:

          【解决方案5】:

          您可以在进程替换中使用grep -fsed,将pattern_file 中的每个扩展名转换为适当的正则表达式:

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

          www.remix3d.com
          www.verisign.net
          

          sed 命令的输出是:

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

          \.com$
          \.re$
          \.net$
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-01-14
            • 1970-01-01
            • 1970-01-01
            • 2017-11-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多