【问题标题】:grep filtering with both pattern and input filegrep 过滤模式和输入文件
【发布时间】:2016-06-21 13:16:51
【问题描述】:

我有一个输入文件,如下所示:

$Interesting line
$Interesting line 2
#Also interesting line
Non interesting line - filter out
$another interesting line
Interesting line contains FiRsT pattern
Another non interesting line
Interesting line contains sec"o^nd pattern
#Interesting line

我有另一个模式文件,其中包含我要过滤的模式(请注意,模式文件可能包含有问题的字符 - 我想将它们称为简单字符,而不是通配符/正则表达式):

FiRsT
sec"o^nd

我希望得到以下结果:

$Interesting line
$Interesting line 2
#Also interesting line
$another interesting line
Interesting line contains FiRsT pattern
Interesting line contains sec"o^nd pattern
#Interesting line

即过滤掉以下两行:

Non interesting line - filter out
Another non interesting line

更准确地说,我希望结果文件中的所有行都包含模式文件的任何字符串,或者行以 # 或 $ 开头(顺序很重要)。

我知道如何从模式文件中过滤字符串:

grep -F -f pattern_file.txt input_file.txt

我知道如何过滤所有以 $ 和 # 开头的行:

grep '^\$\|^#' input_file.txt

但是我应该怎么做呢?唯一的方法是为此编写一个简短的子脚本,还是我仍然可以使用简单的 grep/sed/任何标准的 linux 命令?

再次提醒:

  • 行的顺序很重要,必须与原始输入文件的顺序相匹配。
  • 模式文件可能包含有问题的字符,我想将它们称为常规字符(而不是通配符/正则表达式)。

编辑:考虑以下情况:

输入文件也包含

Interesting line with ^third pattern

模式文件包含

^third

当然,我希望该行出现在结果文件中。这就是为什么我不能引用没有 -F 标志的模式文件,也不能只添加 ^\$ 和 ^# 行。

【问题讨论】:

    标签: linux perl sed grep csh


    【解决方案1】:

    您可以使用awk

    NR==FNR { pattern[NR]= $0; count++; next }
    /^[$#]/ { print ; next }
    {
        for (i = 1; i <= count; i++) {
            if (index($0, pattern[i]) > 0) {
                print; next;
            }
        }
    }
    

    或者,您可以处理您的模式文件并引用所有正则表达式元字符。

    【讨论】:

    • 它有效。但是性能很差(这很关键,因为我的文件很大(例如,模式文件中有 1000 行,输入文件中有 2100 万行)。我猜预加载模式文件而不是每次迭代都使用索引函数可能会提高性能.
    【解决方案2】:

    您可以引用第一个模式文件中的特殊字符,并原封不动地传递第二个模式文件。

     grep -f <(perl -p -e "s#([\^\*])#\\\\\1#g" pattern_file.tx) -f extra_patterns.txt input_file.txt
    

    此示例命令将仅引用 ^*。如果需要,很容易添加其他元字符。

    【讨论】:

      【解决方案3】:

      最后根据其他人的建议解决了 - 通过处理模式文件并转义任何元字符。在这里写下来,因为我发现这是完整且高效的解决方案:

      sed -e 's/\([\.\^\*\[\$\\]\)/\\\1/g' -e 's/]/\\\]/g'  pattern_file.txt > new_pattern_file.txt
      echo '^\#' >> new_pattern_file.txt
      echo '^\$' >> new_pattern_file.txt
      

      然后我可以使用 grep:

      grep -f new_pattern_file.txt input_file.txt
      

      以下是有关应转义的字符列表的更多详细信息: https://unix.stackexchange.com/questions/32355/escaping-of-meta-characters-in-basic-extended-posix-regex-strings-in-grep

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-23
        • 2016-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多