使用模式和输入文件进行 grep 过滤
grep filtering with both pattern and input file
我有一个输入文件,如下所示:
$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/whatever 标准 linux 命令?
再次记住:
- 行的顺序很重要,必须与原始输入文件的顺序相匹配。
- 模式文件可能包含有问题的字符,我想将它们称为常规字符(而不是通配符/正则表达式)。
编辑:考虑以下情况:
输入文件还包含
Interesting line with ^third pattern
花样文件包含
^third
当然,我希望该行位于结果文件中。这就是为什么我不能在没有 -F 标志的情况下引用模式文件,也不能只向其中添加 ^\$ 和 ^# 行。
你可以用 awk
:
NR==FNR { pattern[NR]= [=10=]; count++; next }
/^[$#]/ { print ; next }
{
for (i = 1; i <= count; i++) {
if (index([=10=], pattern[i]) > 0) {
print; next;
}
}
}
或者,您可以处理您的模式文件并引用所有正则表达式元字符。
您可以在第一个模式文件中引用特殊字符,然后不加改动地传递第二个模式文件。
grep -f <(perl -p -e "s#([\^\*])#\\#g" pattern_file.tx) -f extra_patterns.txt input_file.txt
这个示例命令将只引用 ^
和 *
。如果需要,可以轻松添加其他元字符。
最终根据其他人的建议解决了这个问题 - 通过处理模式文件并转义任何元字符。在这里写下来,因为我发现这是完整且高效的解决方案:
sed -e 's/\([\.\^\*\[$\]\)/\/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
我有一个输入文件,如下所示:
$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/whatever 标准 linux 命令?
再次记住:
- 行的顺序很重要,必须与原始输入文件的顺序相匹配。
- 模式文件可能包含有问题的字符,我想将它们称为常规字符(而不是通配符/正则表达式)。
编辑:考虑以下情况:
输入文件还包含
Interesting line with ^third pattern
花样文件包含
^third
当然,我希望该行位于结果文件中。这就是为什么我不能在没有 -F 标志的情况下引用模式文件,也不能只向其中添加 ^\$ 和 ^# 行。
你可以用 awk
:
NR==FNR { pattern[NR]= [=10=]; count++; next }
/^[$#]/ { print ; next }
{
for (i = 1; i <= count; i++) {
if (index([=10=], pattern[i]) > 0) {
print; next;
}
}
}
或者,您可以处理您的模式文件并引用所有正则表达式元字符。
您可以在第一个模式文件中引用特殊字符,然后不加改动地传递第二个模式文件。
grep -f <(perl -p -e "s#([\^\*])#\\#g" pattern_file.tx) -f extra_patterns.txt input_file.txt
这个示例命令将只引用 ^
和 *
。如果需要,可以轻松添加其他元字符。
最终根据其他人的建议解决了这个问题 - 通过处理模式文件并转义任何元字符。在这里写下来,因为我发现这是完整且高效的解决方案:
sed -e 's/\([\.\^\*\[$\]\)/\/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