Напечатайте несопоставленные образцы, используя grep с образцами из файла


15

patterns.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, но я открыт для других инструментов. Извиняюсь, если это дубликат другого вопроса, который я не смог найти.

Ответы:


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.xmlи Strings2.xml), вам также понадобится -hфлаг на первом grep.
Джейхендрен

@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 ( grep -v) с использованием процесса substitution ( <(command)).


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.txtв состоянии patпродолжить вышеуказанную команду на выходе является:

"ExitWarning"
"SomeMessage"
"Help"

cutвыводит в stdout только вторую "двойную кавычку с -dразделителем -field для каждой строки ввода, сопоставленной с разделителем, и -sподавляет все остальные.

Что на cutсамом деле печатает на grepэто:

Introduction
BananaOpinion
MessageToUser

grepищет в названном файловом операнде строки, которые -vне соответствуют -Fixed строкам в его файле -stdin -f.

Если вы можете полагаться на второе "поле с ограничением в качестве того, которое должно соответствовать, то это определенно будет оптимизация по сравнению с grep -Pрежимом erl, просто сопоставляя -Fixed строки и только крошечные их части, потому что 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печатает только уникальные линии.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.