J'essaye de convertir cette ligne de journal:
2019-02-25 00:39:01,[] 2019-02-25 00:50:06,[] 2019-02-25 03:59:42,[]
en une feuille de calcul qui ressemble à ceci:
perl -ne 'print "$1,$2\n" if /\[(.*?)\].+(\[.*\])/' filename
J'ai essayé d'écrire cette ligne
| time | phone number | sms job id | --------------------------------------------------------------------------- | 2019-02-25 00:39:01 | +96605992911111 |000000001328e347000000003113b4f8| | 2019-02-25 00:50:06 | +96605992911112 |00000000206561fd000000003fb01b05| | 2019-02-25 03:59:42 | +96605992911113 |0000000003baa9660000000022c0679c|
mais tout ce que j'ai est ceci:
9:[2019-02-25 00:39:01] production.DEBUG: JOB-VARS : {"phone_numbers":["+9660599291111"],"message":"Your verification code is: 74222","twilio":{},"objectKey":"job:class:App\\Jobs\\SmsJob:000000001328e347000000003113b4f8","connection":"sqs-high","queue":null,"delay":null,"job":{},"JOB-CLASS":"App\\Jobs\\SmsJob"} [] [] 16:[2019-02-25 00:50:06] production.DEBUG: JOB-VARS : {"phone_numbers":["+9660533001112"],"message":"Your verification code is: 31231","twilio":{},"objectKey":"job:class:App\\Jobs\\SmsJob:00000000206561fd000000003fb01b05","connection":"sqs-high","queue":null,"delay":null,"job":{},"JOB-CLASS":"App\\Jobs\\SmsJob"} [] [] 54:[2019-02-25 03:59:42] production.DEBUG: JOB-VARS : {"phone_numbers":["+9647707771113"],"message":"Your verification code is: 64628","twilio":{},"objectKey":"job:class:App\\Jobs\\SmsJob:0000000003baa9660000000022c0679c","connection":"sqs-high","queue":null,"delay":null,"job":{},"JOB-CLASS":"App\\Jobs\\SmsJob"} [] []
Je suis resté coincé en capturant le deuxième groupe. Des idées?
4 Réponses :
Vous pouvez essayer ce modèle \ [([^ \]] ++) \]. + phone \ _numbers \ D ++ (\ d ++). + SmsJob \: (\ w ++)
p>
Explication:
\ [([^ \]] ++) \]
correspondra à la date entre crochets, capturant la date dans un groupe,
. + phone \ _numbers \ D ++ (\ d ++)
correspondra à un ou plusieurs de tous les caractères, puis phone_number
littéralement, puis un ou plusieurs non-chiffres, puis il capturera le numéro de téléphone réel dans un groupe avec (\d++)
. + SmsJob \: (\ w ++)
correspondra d'abord à un ou plusieurs caractères, puis SmsmJob
littéralement, puis :
et puis capturera l'ID de la tâche dans un autre groupe de capture
Se fier entièrement aux détails du format, avec tous les "
et []
etc
perl -wnE' say "$1, $2, $3" if /:\[(.*?)\].*?"phone_numbers":\["(.*?)"\].*?SmsJob:(.*?)"/ ' file
où j'utilise des phrases explicites (comme "phone_numbers":
) pour ancrer les modèles nécessaires.
Notez les modèles non gourmands partout. Puisque nous avons des "ancres" textuelles pratiques pour ce que nous devons capturer, il n'y a aucune raison pour laisser les schémas gourmands se déchaîner; ils sont beaucoup plus difficiles à suivre mentalement, peuvent être difficiles à obtenir et sont généralement moins efficaces. †
Notez que j'utilise "
après SmsJob
car SmsJob:
vient en dernier dans objectKey
et il se trouve que "
a raison après, ce qui est pratique pour délimiter le motif à correspondre. Mais si ce "
n'est pas certain d'être là, alors . *?
doit être changé; peut-être à [0-9a-zA-Z]
(modèle minimal pour ce qui est autorisé dans la valeur SmsJob
), suivi d'un caractère littéral qui le termine (comme ,
ou :
etc).
Ceci capture correctement l'horodatage et le numéro de téléphone et SmsJob à partir de l'échantillon donné.
† Le deuxième modèle de la tentative honnête de la question ne parvient pas à capturer ce qui est attendu car le gourmand . +
saisit tout jusqu'au bout dernière paire []
dans la chaîne, puisque le \ [. * \]
qui vient après . +
correspond à ce dernier [ ]
donc tout le motif correspond de cette façon.
Votre regex actuelle est tellement gourmande et la chaîne d'entrée donnée est sûrement différente. Vous n'avez pas non plus essayé d'obtenir trois groupes de capture. Essayez plutôt ceci:
perl -ne 'print "$1,$2,$3\n" if /\[([\d: -]+)\][^][]+\["([^][]+)"\].*?SmsJob:(\w+)/' filename
Perl:
\[([\d: -]+)\][^][]+\["([^][]+)"\].*?SmsJob:(\w+)
Répartition des expressions régulières:
\ [
Match [
littéralement (
Début du premier groupe de capture
[\ d: -] +
Correspond à une combinaison de caractères spécifiés (chiffre, :
, espace et -
) )
Fin du groupe de capture \]
Match ]
littéralement [^] [] +
Correspond à tout sauf à [
et
\ ["
Match ["
littéralement (
Début du deuxième groupe de capture
[^] [] +
Correspond à tout sauf à [
et
)
Fin du groupe de capture "\]. *? SmsJob:
Correspond à SmsJob:
(\ w +)
Faire correspondre une séquence de caractères de mots et stocker dans le 3ème groupe de capture Pour moi, votre "JOB-VARS" ressemble beaucoup à JSON. Envisagez peut-être d'utiliser le module JSON.
use strict; use warnings; use JSON; my $json= new JSON; while (<>) { my ($ts, $jtext)= /\[(.*?)\] production.DEBUG: JOB-VARS : (.*)/; my ($obj)= $json->decode_prefix($jtext); my $phone_number= $obj->{phone_numbers}->[0]; my $jid= $obj->{objectKey}; $jid=~ s/^.*://; printf "| %19s | %-15s |%32s|\n",$ts,$phone_number,$jid; }
Essayez ceci
En exécutant la même commande perl sur ce fichier, j'obtiens des résultats différents mais attendus. Êtes-vous sûr que la chaîne d'entrée est la même que celle que vous avez publiée?
@revo désolé j'ai supprimé des fichiers indésirables, le fichier journal réel ressemble à ceci
@Potato .. ça a marché comme un charme!
Remarque - vous capturez et imprimez deux choses, alors que trois sont nécessaires? De plus, je suppose que les données affichées sont correctes (et qu'un peu plus qu'il y en a sur chaque ligne, comme on le voit sur le lien donné ci-dessus, est exactement comme vu dans ce lien, n'affectant pas les modèles)
Le deuxième modèle de votre expression régulière correspond au
[]
vide à la fin de la ligne (vu dans le lien, pas dans la question) en raison de la gourmandise de. +
question mise à jour pour inclure les journaux réels pour éviter toute confusion
cela a parfaitement fonctionné! je t'ai accordé la bonne réponse
Génial, bon d'entendre tout est bon :) Et merci de vous en être occupé.