2
votes

Extraire les correspondances de motif / Tout supprimer de la ligne sauf le motif

J'utilise actuellement grep pour essayer d'extraire du texte spécifique de chaque ligne d'un fichier. Il réussit à extraire les correspondances, cependant, j'aimerais qu'il conserve toutes les lignes qui n'ont pas de correspondance (laissez-les comme une ligne vide).

C'est ce que j'ai essayé jusqu'à présent (pour obtenir le nom du ville sur chaque ligne):

north tonawanda

DOTHAN
NORCROSS
HOLLYWOOD

Exemple d'entrée:

email":"addictedtotlick7@gmail.com","last_name":"THOMPSON","first_name":"ERIN",,"__v":0,,,,"state":"NY","city":"north tonawanda"}
first_name":"chris","last_name":"caul",,"email":"dawgzn@mail.com",,,,"__v":0}
email":"lesliebo993@hotmail.com",,"first_name":"LESLIE","last_name":"RAMBO",,"city":"DOTHAN","state":"AL",,,"__v":0,
email":"malala@yahoo.com",,,"state":"GA","city":"NORCROSS",,"last_name":"KEO","first_name":"CATHY",,"__v":0,
email":"kdela@gmail.com",,"state":"FL","city":"HOLLYWOOD",,"last_name":"DE LA CRUZ","first_name":"KIDA",,"__v":0,

Sortie souhaitée:

grep -o -P '(?<="city":").*?(?=")' input.txt

Heureux d'essayer quelque chose dans SED aussi si c'est plus facile, mais je préférerais éviter AWK car je dois travailler avec de gros fichiers, je ne suis pas sûr d'avoir assez de RAM.


4 commentaires

grep semble ignorer les correspondances vides.


Avez-vous un awk GNU? Essayez gawk '{print index ($ 0, "\" city \ ": \" ") == 0?" ": Gensub (/.* \" city \ ": \" ([^ \ "] * ). * /, "\\ 1", $ 0);} 'fichier> nouveau fichier


@ WiktorStribiżew - cela semble produire la sortie correcte quand je l'exécute, mais j'obtiens ceci dans la console pour chaque ligne: gawk: cmd. ligne: 1: (FILENAME = db1.txt FNR = 100000) avertissement: gensub: troisième argument `email": "uccelds@cox.net" , "__ v": 0 , "state": "CT", " city ​​":" Ro‌ cky Hill "," last_name ":" Uccello "," first_name ":" Sebastiano "} 'traité comme 1


Ok, compris. Affectation.


4 Réponses :


1
votes

Vous pouvez le faire avec GNU awk:

gawk '{print index($0, "\"city\":\"") == 0 ? "" : gensub(/.*\"city\":\"([^\"]*).*/, "\\1", 1);}' file > newfile

Cela signifie: si la ligne contient "city": " ( index ($ 0, "\" city \ ": \" ") == 0 ) puis (? ) imprime une ligne vide (" " code>) ou (: ) imprime le résultat de gensub (/.* \ "city \": \ "([^ \"] *). * /, "\\ 1 ", 1) remplacement de l'expression régulière:

  • . * - 0 caractère ou plus
  • \ "city \": \ " - une sous-chaîne de " city ":"
  • ([^ \ "] *) - Groupe de capture 1 ( \ 1 ): 0 ou plus de caractères autres que " li>
  • . * - 0 caractère ou plus.

Le résultat est la valeur du groupe 1. Nous avons besoin de gensub et donc de GNU awk car nous avons besoin d'accéder à la valeur du groupe de capture.


0 commentaires

-1
votes

Je suggère un autre script awk

awk 'match($0,/(?<=\"city\":\").*?(?=\")/,m){$0=m[0]}1' input.txt

Aucun problème avec la RAM et awk.

Ce script traite chaque ligne. Si la ligne actuelle correspond à RegExp (? , remplacez la ligne actuelle par match. Imprimer la ligne actuelle.


0 commentaires

0
votes

Sed:

sed 's/.*city":"\([^"]*\).*/|\1/; /^[^|]/s/.*//; s/^|//'


1 commentaires

Et, en parlant de gros fichiers, sed est également beaucoup plus rapide.



1
votes

Vous pouvez essayer Perl

$ perl -nle ' if(/"city":"(.*?)"/) { print $1 } else { print "" } ' input.txt
north tonawanda

DOTHAN
NORCROSS
HOLLYWOOD

$


0 commentaires