Imprimer des motifs inégalés, en utilisant grep avec des motifs à partir d'un fichier


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>

Production attendue:

"ExitWarning"
"SomeMessage"
"Help" 

Comment imprimer les termes patterns.txtqui ne se trouvent pas dans Strings.xml? Je peux imprimer les apparié / inégalés lignes dans Strings.xml, mais comment puis-je imprimer les incomparables modèles ? J'utilise la version 2.21 de ggrep (GNU grep), mais je suis ouvert à d'autres outils. Toutes mes excuses s'il s'agit d'un doublon d'une autre question que je n'ai pas pu trouver.

Réponses:


25

Vous pouvez utiliser grep -opour imprimer uniquement la partie correspondante et utiliser le résultat comme modèles pendant une seconde grep -vsur le patterns.txtfichier d' origine :

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

Bien que dans ce cas particulier, vous puissiez également utiliser join+ sort:

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

c'est assez élégant .. intelligent!
XXL

Si vous avez plusieurs fichiers d'entrée (par exemple Strings1.xmlet Strings2.xml), vous aurez également besoin du -hdrapeau sur le premier grep.
jayhendren

@jayhendren - oui, mais tous ne grepprennent pas en charge cette option. Si vous avez plusieurs fichiers d'entrée, je ne vois pas pourquoi vous ne pourriez pas simplement catles tous et diriger le résultat grep.
don_crissti

5

La meilleure approche est probablement ce que @don_crissti a suggéré, voici donc une variation sur le même thème:

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

C'est fondamentalement l'inverse de l'approche de @ don_crissti. Il utilise grep avec des expressions régulières compatibles Perl ( -P) et le -ocommutateur pour imprimer uniquement la partie correspondante de la ligne. Ensuite, l'expression régulière la recherche name=et la rejette ( \K), puis recherche un ou plusieurs caractères jusqu'au premier "( .+?"). Il en résulte la liste des modèles présents dans le String.txtfichier qui est ensuite passée en entrée à un grep ( grep -v) inverse en utilisant la substitution de processus ( <(command)).


2

j'utiliserais cut probablement. Autrement dit, si, comme il apparaît, vous savez où attendre la chaîne entre guillemets que vous recherchez.

Si je fais:

{   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

... après avoir enregistré ma propre copie de votre exemple patterns.txtdans patet exécuté la commande ci-dessus, le résultat est:

"ExitWarning"
"SomeMessage"
"Help"

cutimprime à stdout la deuxième "guillemet -delimited -field pour chaque ligne associée délimiteurs d'entrée et -suppresses tous les autres.

Ce cutqui s'imprime réellement grepest:

Introduction
BananaOpinion
MessageToUser

greprecherche dans son opérande de fichier nommé des lignes qui -vne correspondent pas aux -Fchaînes ixées dans son -fichier de modèle stdin -f.

Si vous pouvez compter sur le deuxième "champ délimité comme celui qui correspond, alors ce sera certainement une optimisation par grep -Prapport au mode erl en faisant simplement correspondre des -Fchaînes ixées et seulement de minuscules portions d'entre elles, car cutcela soulève des charges lourdes - et cela se fait rapidement .


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

il est facile à comprendre mais a le temps d'arrêt de générer plusieurs processus grep, un pour chaque ligne dans patterns.txt.


0

une autre façon consiste à mettre patterns.txt et Strings.xml dans une liste et à trouver des lignes uniques

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

explication:

cat patterns.txt Strings.xmlmet tout en une seule liste. grep -oFf patterns.txtsupprime les ordures sur chaque ligne. sortexplicite. trier toutes les lignes. uniq -uimprime uniquement des lignes uniques.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.