使用grep和文件中的图案一起打印不匹配的图案


15

pattern.txt:

"BananaOpinion"
"ExitWarning"
"SomeMessage"
"Help"
"Introduction"
"MessageToUser"

Strings.xml

<string name="Introduction">One day there was an apple that went to the market.</string>
<string name="BananaOpinion">Bananas are great!</string>
<string name="MessageToUser">We would like to give you apples, bananas and tomatoes.</string>

预期产量:

"ExitWarning"
"SomeMessage"
"Help" 

如何打印在中patterns.txt找不到的条款Strings.xml?我可以打印匹配/不匹配的线路Strings.xml,但我如何打印出无与伦比的模式?我正在使用ggrep(GNU grep)2.21版,但可以使用其他工具。抱歉,如果这是我找不到的另一个问题的重复。

Answers:


25

您可以grep -o只打印匹配的部分,然后将结果用作模式grep -v在原始patterns.txt文件上进行一秒钟:

grep -oFf patterns.txt Strings.xml | grep -vFf - patterns.txt

尽管在这种情况下,您也可以使用join+ sort

join -t\" -v1 -j2 -o 1.1 1.2 1.3 <(sort -t\" -k2 patterns.txt) <(sort -t\" -k2 strings.xml)

这是相当优雅..聪明!
XXL

如果您有多个输入文件(例如Strings1.xmlStrings2.xml),则还需要-h第一个grep上的标志。
jayhendren

@jayhendren-是的,但并非所有人都grep支持该选项。如果您有多个输入文件,我不明白为什么不能简单地将cat它们全部都输入到管道中grep
don_crissti

5

最好的方法可能是@don_crissti建议的方法,因此这是同一主题的一种变形:

$ grep -vf <(grep -Po 'name=\K.+?"' Strings.xml) patterns.txt
"ExitWarning"
"SomeMessage"
"Help"

这基本上是@don_crissti方法的反面。它使用grep与Perl兼容的正则表达式(-P)和-o开关一起仅打印行中匹配的部分。然后,正则表达式将查找name=并丢弃它(\K),然后查找一个或多个字符,直到第一个".+?")。这将导致String.txt文件中存在的模式列表,然后grep -v使用流程替换<(command))作为输入传递给反向grep ()。


2

我可能会用cut。就是说,如果它看起来像您所知道的那样,您知道在哪里可以找到所引用的字符串。

如果我做:

{   cut  -sd\" -f2 |
    grep -vFf- pat
}   <<\IN
#   <string name="Introduction">One day there was an apple that went to the market.</string>
#   <string name="BananaOpinion">Bananas are great!</string>
#   <string name="MessageToUser">We would like to give you apples, bananas and tomatoes.</string>
IN

...救了我自己的例子拷贝后patterns.txtpat运行上述命令的输出是:

"ExitWarning"
"SomeMessage"
"Help"

cut打印到标准输出仅第二"双引号-delimited -field每个输入分隔符匹配线和-suppresses所有其他人。

什么cut实际打印的grep是:

Introduction
BananaOpinion
MessageToUser

grep在其命名的文件操作数中搜索-v与stdin模式ile中的固定-F字符串不匹配的行。--f

如果您可以将第二个以"空格分隔的字段作为匹配项,那肯定是对grep -Perl模式的优化,-F因为它只匹配固定的字符串,并且只匹配其中的一小部分,因为cut这样做很繁琐-而且速度很快


1
for p in $(cat patterns.txt); do if ! grep $p strings.xml &>/dev/null; then echo $p; fi; done

这很容易理解,但是会产生多个grep进程的停机时间,patterns.txt中的每一行都有一个。


0

另一种方法是将patterns.txt和Strings.xml放在一个列表中并查找唯一的行

cat patterns.txt Strings.xml | grep -oFf patterns.txt | sort | uniq -u

说明:

cat patterns.txt Strings.xml将所有内容都放在一个列表中。 grep -oFf patterns.txt删除每行上的垃圾。 sort不言自明。对所有行进行排序。 uniq -u仅打印唯一的行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.