使用模式和输入文件进行grep过滤

时间:2016-06-21 13:16:52

标签: linux perl sed grep csh

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

$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

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

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

grep -F -f pattern_file.txt input_file.txt

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

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

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

再次,请记住:

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

修改:请考虑以下情况:

输入文件也包含

Interesting line with ^third pattern

模式文件包含

^third

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

3 个答案:

答案 0 :(得分: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;
        }
    }
}

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

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

最后根据其他建议解决了这个问题 - 处理模式文件并转义任何元字符。把它写在这里,因为我发现这是一个完整且高性能的解决方案:

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