extraire un motif et un certain champ de la ligne au-dessus en utilisant awk et grep de préférence

J’ai un fichier texte comme celui-ci:

********** time1 ********** line of text1 line of text1.1 line of text1.2 ********** time2 ********** ********** time3 ********** ********** time4 ********** line of text2.1 line of text2.2 ********** time5 ********** ********** time6 ********** line of text3.1 

Je veux extraire la ligne de texte et l’heure (sans les écanvass) au-dessus et la stocker dans un fichier (le temps sans ligne de texte en dessous doit être ignoré ). Je veux le faire de préférence avec grep et awk. Donc, par exemple, ma sortie pour le code ci-dessus devrait être

 time1 : line of text1 time1 : line of text1.1 time1 : line of text1.2 time4 : line of text2.1 time4 : line of text2.2 time6 : line of text3 

comment puis-je y aller?

Cela suppose qu’il n’y a pas d’espace dans le temps et qu’il n’y a qu’une seule ligne de texte après chaque marqueur de temps.

 awk '$1 ~ /\*+/ {prev = $2} $1 !~ /\*+/ {print prev, ":", $0}' inputfile 

Fonctionne avec des espaces dans le temps:

 awk '/^[^*]+/ { gsub(/*/,"",x);printf x": "; print };{x=$0}' data.txt 

Vous pouvez le faire comme ça avec vim :

 :%s_\*\+ \(YOUR TIME PATTERN\) \*\+\_.\(\[^*\].*\)$_\1 : \2_ | g_\*\+ YOUR TIME PATTERN \*\+_d 

C’est-à-dire rechercher les lignes TIME PATTERN et enregistrer le modèle de temps et la ligne suivante s’il n’a pas démarré avec * . Ensuite, créez la nouvelle ligne à partir d’eux. Supprimez ensuite chaque ligne TIME PATTERN restante.

Notez que cela suppose que les lignes de modèle de temps se terminent par * , etc.

Avec awk :

 awk '/\*+ YOUR TIME PATTERN \*+/ { time=gensub("\*+ (YOUR TIME PATTERN) \*+","\\1","g") } ! /\*+ YOUR TIME PATTERN \*+/ { print time " : " $0 }' INPUTFILE 

Et il y a d’autres façons de le faire.

En awk, voir:

 #!/bin/bash awk ' BEGIN{ t=0 } { if ($0 ~ " time[0-9]+ ") { v=$2 t=1 } else if ($0 ~ "line of text") { if (t==1) { printf("%s : %s\n", v, $0) } else { t=0; } } } ' FILE 

Remplacez simplement FILE par votre nom de fichier.

Cela pourrait fonctionner pour vous (GNU sed):

 sed '/^\*\+ \S\+.*/!d;s/[ *]//g;$!N;/\n[^*]/!D;s/\n/ : /' file 

Explication:

  • Recherchez les lignes commençant par * si elles ne sont pas supprimées. /^\*\+ \S\+.*/!d
  • J’ai une chronologie. Supprimer les * et les espaces (heure de départ). s/[ *]//g
  • Obtenez la prochaine ligne $!N
  • Vérifiez que la deuxième ligne ne commence pas par * sinon supprimez la première ligne /\n[^*]/!D
  • Vous avez le motif voulu, remplacez \n par un espacement : et imprimez. s/\n/ : /
 awk '{ if( $0 ~ /^\*+ time[0-9] \*+$/ ) { time = $2 } else { print time " : " $0 } }' file 
 $ uniq -f 2 input-file | awk '{getline n; print $2 " : " n}' 

Si votre horodatage contient des espaces, remplacez l’argument par l’option -f afin uniq compare uniquement la chaîne finale de * . Par exemple, utilisez -f X où X-2 est le nombre d’espaces dans l’horodatage. De même, s’il y a des espaces dans l’horodatage, le awk devra changer. L’un ou l’autre fonctionnera:

 $ uniq -f 3 input-file | awk -F '**********' '{getline n; print $2 " : " n}' $ uniq -f 3 input-file | awk '{getline n; $1=""; $NF=""; print $0 ": " n }'