5 votes

Déplacer le motif au début de la ligne

J'essaie de reformater un fichier journal de manière à ce que la date et l'heure apparaissent au début de la ligne. Mes journaux ressemblent à ceci :

blah, blah, blah, Friday, Mar 13,2015 16:59:42
yadi, yadi, yada, Friday, Mar 13,2015 16:51:11

Je voudrais qu'ils ressemblent à ça :

Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada

Je suis allé jusqu'à trouver le bon modèle grep avec grep -o -i -e '[a-zA-Z]*, [a-z][a-z][a-z] [0-9]*,[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]' ~/log.txt .

Comment puis-je déplacer ces résultats de motifs à gauche de la chaîne d'information ? Merci pour votre aide.

5voto

heemayl Points 85741

Essayez sed avec la regex suivante :

$ sed -i.bak 's_\(.*\),[[:blank:]]\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)_\2 \1_' file.txt 
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada

Ici, nous avons utilisé le sed pour obtenir le résultat souhaité.

  • \(.*\) correspondra à blah, blah, blah comme nous l'avons fait ,[[:blank:]] pour correspondre , après elle.
  • \([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\) correspondra à la partie restante de la ligne (la partie que nous voulons mettre au début).

Alors nous avons \2 \1 pour mettre le deuxième groupe en premier, puis un espace et ensuite le premier groupe.

Le fichier original sera sauvegardé en tant que file.txt.bak si vous ne voulez pas que cela soit le cas, utilisez simplement -i au lieu de -i.bak .

**Bien que vous obteniez le résultat souhaité, l'utilisation de Regex/sed n'est pas la solution optimale dans ce cas.

EDIT : Si vous avez une ligne comme [Internet disconnected] Friday, Mar 13,2015 15:48:34 essayez ceci :

$ sed -i.bak 's_\(.*[^,]\),*[[:blank:]]\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)_\2 \1_' file.txt 
Friday, Mar 13,2015 15:48:34 [Internet disconnected]
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada

Dans la regex précédente, nous avions \(.*\),[[:blank:]] (une virgule et un espace après le premier groupe correspondant), maintenant pour inclure la nouvelle ligne dans la sortie nous avons fait le premier groupe correspondant \(.*[^,]\) pour s'assurer qu'il ne se termine pas par une virgule et ensuite nous avons fait correspondre ,* c'est-à-dire une ou plusieurs virgules. Ainsi, le nouveau sed fonctionnera pour tous les cas mentionnés.

4voto

Panther Points 96601

Avec awk, la syntaxe est beaucoup plus simple

awk -F, '{print $4","$5","$6","$1","$2","$3}' file.txt

3voto

Stewart Points 1385

La règle d'or des expressions régulières est "moins, c'est plus". Vous devez toujours essayer d'écrire la plus simple des expressions régulières correspondant à vos données. Non seulement elle est beaucoup plus facile à lire et à comprendre, mais elle est aussi beaucoup plus robuste et ne se cassera pas avec de petits changements de format. Donc, dans votre cas, vous pourriez simplement faire :

$ sed -r 's/(.*), ([^,]+,[^,]+,[^,]*$)/\2\1/' file 
Friday, Mar 13,2015 16:59:42blah, blah, blah, 
Friday, Mar 13,2015 16:51:11yadi, yadi, yada, 

Cela correspond à tout ce qui se trouve depuis le début de la ligne jusqu'à une virgule et un espace ( (.*), ) et, parce que le motif est entouré de parenthèses, il l'enregistre sous le nom de \1 . Maintenant, parce que le deuxième groupe capturé (deuxième motif entre parenthèses) va jusqu'à la fin de la ligne (c'est ce que fait le $ signifie), on sait que l'on fait correspondre la bonne partie dans la première.

La seconde recherche un tronçon d'un ou plusieurs caractères non-comma ( [^,]+ ), une virgule, une autre série de non-comma, une autre virgule et ensuite autant de caractères non-comma que possible jusqu'à la fin de la ligne. De cette façon, nous pouvons identifier correctement les derniers champs comme étant la date. Le site s/// est l'opérateur de substitution qui, ici, change simplement l'ordre du premier et du deuxième motif capturé.

Vous pouvez également faire la même chose dans awk . On peut supposer que le texte précédant la date est variable et que nous ne pouvons pas supposer le même nombre de champs pour chaque ligne. Par conséquent, nous devrons compter les champs à rebours à partir de la fin de la ligne :

$ awk -F, '{ 
            printf "%s,%s,%s, ", $(NF-2),$(NF-1),$NF; 
            for(i=1;i<NF-3;i++){printf "%s,", $i} print $(NF-3)
         }' file 
 Friday, Mar 13,2015 16:59:42, blah, blah, blah
 Friday, Mar 13,2015 16:51:11, yadi, yadi, yada

Ou en Perl :

$ perl -lpe 's/(.*), ([^,]+,[^,]+,[^,]*$)/\2, \1/' file 
Friday, Mar 13,2015 16:59:42, blah, blah, blah
Friday, Mar 13,2015 16:51:11, yadi, yadi, yada

$ perl -F, -lane 'print join ",",@F[$#F-2,$#F-1,$#F,0..$#F-3]' file 
 Friday, Mar 13,2015 16:59:42,blah, blah, blah
 Friday, Mar 13,2015 16:51:11,yadi, yadi, yada

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X