J'ai un fichier texte ( file.txt
) qui contient un mur de résultats (pas de sauts de ligne, d'espaces, etc.) que j'ai reçu d'une source externe. À partir de ce fichier, je dois trouver toutes les mentions du mot serId
, puis imprimer la séquence alphanumérique qui le suit. La séquence alphanumérique est de n'importe quelle longueur mais se terminera par le caractère ,
. Comment puis-je extraire ces séquences alphanumériques?
J'ai essayé de trouver des scripts / code en utilisant sed / awk mais les résultats semblent tourner autour d'une séquence connue à trouver, plutôt que d'une séquence inconnue.
Par exemple, je voudrais extraire 28655784-EE
de l'exemple de texte suivant:
{"preRollbackCheckResults":[],"patchingHistory":[{"backupStatus":"Available","rollbackStatus":"Available","additionalNote":"Patching CDS as planned","appliedBy":"xxrbsgCDS02services","appliedDate":"2019-01-18T12:45:33.926+0000","totalTime":"29 min, 47 sec","serId":"28655784-EE","patchDescription":"DB 18.4.0.0.0 Oct 2018 PSU
4 Réponses :
Essayez ce script awk (gawk uniquement):
awk -F '","' 'match($0,/serId\":\"[^,]*/,m){print m[1]","}' input.txt
Si vous avez besoin du ,
awk -F '","' 'match($0,/serId\":\"[^,]*/,m){print m[1]}' input.txt
explication:
-F ","
analyse le fichier en enregistrements séparés par ,
match ($ 0 , "serId [^,] *", m)
filtre dans l'enregistrement courant, correspondant à une chaîne commençant par serId
se terminant par ,
. Mettre le résultat dans le tableau m
print substr (m [0], 8)
imprimer la chaîne correspondante à partir de la 8ème position
p >
Cela a fonctionné lorsque j'ai combiné votre solution avec celle de Dominique. Merci beaucoup.
Je l'ai fait mais le vote positif ne persistera pas. Je ne sais pas pourquoi?
Ah. "Les votes exprimés par ceux qui ont moins de 15 points de réputation sont enregistrés, mais ne modifient pas le score affiché publiquement." Mais j'ai voté pour.
Le deuxième argument de match () est une expression rationnelle, pas une chaîne, vous devez donc utiliser l'expression régulière /
au lieu des délimiteurs de chaîne "
, c'est-à-dire match ($ 0, / serId ":" [^,] * /, ..)
au lieu de match ($ 0, "serId \": \ "[^,] *", ..)
. [^,] *
devrait vraiment être [^ "] *
cependant et tout l'intérêt d'utiliser gawk pour le 3e argument à match () est d'isoler les segments de l'expression rationnelle capturez les groupes à référencer dans le bloc d'action afin que le code soit vraiment match ($ 0, / serId ":" ([^ "] *) /, m) {print m [1]}
sinon avec n'importe quel awk que vous pouvez écrire match ($ 0, / serId ":" [^ "] * /) {print substr ($ 0, RSTART + 8, RLENGTH-8)}
Merci à @Ed Morton, mis à jour avec les recommandations.
De rien. Vous avez cependant besoin des parenthèses pour créer le groupe de capture et vous n'avez pas besoin d'échapper les guillemets doubles à l'intérieur des /
s donc utilisez / serId ":" ([^ "] *) /
pas / serId \ ": \" [^,] * /
grep -o
est une solution très simple pour cela:
J'ai créé un fichier, contenant les lignes suivantes:
serIdABCde123;
La première ligne ne se termine pas par un point-virgule, la troisième ligne commence par le mauvais mot, donc seule la deuxième ligne est correcte.
J'ai lancé la commande suivante: grep -o " serId [0-9a-zA-Z] *; " testtttt.txt
, avec le résultat suivant:
serId12345 serIdABCde123; Ser_idblabla;
Cela a fonctionné lorsque j'ai combiné votre solution avec celle de Dudi Boy. Merci beaucoup.
Sur la base du court exemple que vous avez publié dans un commentaire, j'ai deux suggestions:
Si le fichier est un json
a>, essayez de comprendre sa structure et utilisez jq
.
S'il est mal formé et ne peut être interprété que comme un tas de texte, utilisez le Perl suivant:
$ cat file.txt {"preRollbackCheckResults":[],"patchingHistory":[{"backupStatus":"Available","rollbackStatus":"Available","additionalNote":"Patching CDS as planned","appliedBy":"xxrbsgCDS02services","appliedDate":"2019-01-18T12:45:33.926+0000","totalTime":"29 min, 47 sec","serId":"28655784-EE","patchDescription":"DB 18.4.0.0.0 Oct 2018 PSU{"preRollbackCheckResults":[],"patchingHistory":[{"backupStatus":"Available","rollbackStatus":"Available","additionalNote":"Patching CDS as planned","appliedBy":"xxrbsgCDS02services","appliedDate":"2019-01-18T12:45:33.926+0000","totalTime":"29 min, 47 sec","serId":"28655784-EE","patchDescription":"DB 18.4.0.0.0 Oct 2018 PSU $ perl -lne '@m=/"serId":"([^"]+)"/g; print "@m"' file.txt 28655784-EE 28655784-EE
Exécution de test:
perl -lne '@m=/"serId":"([^"]+)"/g; print "@m"' file.txt
Avec n'importe quel sed:
$ sed 's/.*"serId":"\([^"]*\).*/\1/' file 28655784-EE
fournir un exemple de fichier d'entrée. pour une séquence inconnue, vous utilisez la correspondance RegEx. ask est l'outil.
J'utilise grep 2.20 et il semble prendre en charge l'option -o. Et un exemple du fichier .txt serait t {"preRollbackCheckResults": [], "patchingHistory": [{"backupSta tus": "Available", "ro llbackStatus": "Disponible", "additionalNot e ":" Correctif CDS comme prévu "," applyBy ":" xxrbsgCDS02services "," appliedDate ":" 20 19-01-18T12: 45: 33.92 6 + 0000 "," totalTime ": " 29 min , 47 sec "," serId ":" 28655784-EE "," patchDescription ":" DB 18.4.0.0.0 oct 2018 PSU ... Donc ce que j'essaierais de faire est de trouver "serId" dans le fichier puis d'extraire "28655784-EE", qui le suit.
Je ne suis pas sûr mais cela ressemble à un fichier
json
, avez-vous regardéjq
?modifiez votre question pour afficher un exemple d'entrée concis et testable et la sortie attendue afin que nous puissions vous aider. La bonne solution n'est PAS de combiner grep + awk comme vous semblez vous en diriger dans vos commentaires sous les réponses actuelles de grep et awk.