Drukuj niedopasowane wzory, używając grep z wzorami z pliku


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>

Oczekiwany wynik:

"ExitWarning"
"SomeMessage"
"Help" 

Jak wydrukować warunki patterns.txt, których nie ma w Strings.xml? Mogę drukować dopasowane / niedopasowane wiersze w Strings.xml, ale jak mogę wydrukować niedopasowane wzorców ? Używam ggrep (GNU grep) w wersji 2.21, ale jestem otwarty na inne narzędzia. Przepraszam, jeśli jest to duplikat innego pytania, którego nie mogłem znaleźć.

Odpowiedzi:


25

Możesz użyć grep -odo wydrukowania tylko pasującej części i wykorzystać wynik jako wzory na sekundę grep -vw oryginalnym patterns.txtpliku:

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

Chociaż w tym konkretnym przypadku możesz również użyć join+ sort:

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

to jest dość eleganckie .. inteligentne!
XXL,

Jeśli masz wiele plików wejściowych (np. Strings1.xmlI Strings2.xml), będziesz również potrzebował -hflagi przy pierwszym grep.
jayhendren

@jayhendren - tak, ale nie wszyscy grepwspierają tę opcję. Jeśli masz wiele plików wejściowych, nie rozumiem, dlaczego nie mogłeś catich wszystkich po prostu przesłać do wyniku grep.
don_crissti

5

Prawdopodobnie najlepsze podejście sugeruje @don_crissti, więc oto wariacja na ten sam temat:

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

Zasadniczo jest to odwrotność podejścia @ don_crissti. Używa grep z wyrażeniami regularnymi zgodnymi z Perl ( -P) i -oprzełącznikiem, aby wydrukować tylko pasującą część linii. Następnie wyrażenie regularne szuka go name=i odrzuca ( \K), a następnie szuka jednego lub więcej znaków do pierwszego "( .+?"). Powoduje to wyświetlenie listy wzorców obecnych w String.txtpliku, które są następnie przekazywane jako dane wejściowe do odwrotnego grep ( grep -v) za pomocą procesowego podstawiania ( <(command)).


2

Chciałbym używać cut, prawdopodobnie. To znaczy, jeśli, jak się wydaje, wiesz, gdzie możesz oczekiwać szukanego ciągu cytowanego.

Jeśli zrobię:

{   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

... po zapisaniu własną kopię przykład patterns.txtw pati działa powyższego polecenia wyjście jest:

"ExitWarning"
"SomeMessage"
"Help"

cutwypisuje na standardowe wyjście tylko drugi "podwójny cudzysłów -deliminowany -fdla każdej linii wejściowej dopasowanej do separatora i -spodwyższa wszystkie pozostałe.

W cutrzeczywistości drukuje się w grep:

Introduction
BananaOpinion
MessageToUser

grepprzeszukuje nazwany operand pliku w poszukiwaniu linii, które -vnie pasują do -Fixed ciągów we -wzorcu stdin -f.

Jeśli możesz polegać na drugim "ograniczonym polu jako tym, które pasuje, to z pewnością będzie to optymalizacja w grep -Ptrybie -Ferl, po prostu dopasowując ixowane struny i tylko ich małe części, ponieważ cutwykonuje ciężkie podnoszenie - i robi to szybko .


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

jest łatwy do zrozumienia, ale ma czas przestoju odradzania wielu procesów grep, po jednym dla każdej linii w pliku patterns.txt.


0

innym sposobem jest umieszczenie patterns.txt i Strings.xml w jednej liście i znajdowanie unikalnych wierszy

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

wyjaśnienie:

cat patterns.txt Strings.xmlumieszcza wszystko na jednej liście. grep -oFf patterns.txtusuwa śmieci z każdej linii. sortoczywiste. posortuj wszystkie linie. uniq -udrukuje tylko unikalne linie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.