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 Réponses :
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.
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.
Sed:
sed 's/.*city":"\([^"]*\).*/|\1/; /^[^|]/s/.*//; s/^|//'
Et, en parlant de gros fichiers, sed est également beaucoup plus rapide.
Vous pouvez essayer Perl
$ perl -nle ' if(/"city":"(.*?)"/) { print $1 } else { print "" } ' input.txt north tonawanda DOTHAN NORCROSS HOLLYWOOD $
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.