Dans sed ou awk, comment puis-je gérer des séparateurs d'enregistrement qui peuvent * s'étendre sur plusieurs lignes?

StackOverflow https://stackoverflow.com/questions/310191

  •  10-07-2019
  •  | 
  •  

Question

Mon fichier journal est:

 Wed Nov 12 blah blah blah blah cat1
 Wed Nov 12 blah blah blah blah
 Wed Nov 12 blah blah blah blah 
 Wed Nov 12 blah blah blah blah cat2
     more blah blah
     even more blah blah
 Wed Nov 12 blah blah blah blah cat3
 Wed Nov 12 blah blah blah blah cat4

Je souhaite analyser les entrées multilignes complètes dans lesquelles cat se trouve sur la première ligne. Quelle est la meilleure façon de procéder dans sed et / ou awk ?

i.e. je veux que mon analyse produise:

 Wed Nov 12 blah blah blah blah cat1
 Wed Nov 12 blah blah blah blah cat2
     more blah blah
     even more blah blah
 Wed Nov 12 blah blah blah blah cat3
 Wed Nov 12 blah blah blah blah cat4
Était-ce utile?

La solution

si vous dites que chaque ligne commençant par un espace est une continuation de la suite de son facile avec (g) awk (c'est de ma mémoire, alors peut-être qu'elle contient quelques fautes de frappe mineures, et pour une meilleure lisibilité avec quelques sauts de ligne supplémentaires):

awk " BEGIN { multiline = 0;} 
      ! /^ / { if (whatever) 
                 { print; multiline = 1;} 
               else 
                 multiline = 0; 
             } 
        /^ / {if (multiline == 1) 
                 print;
             } 
     " 
      yourfile

quel que soit soit votre contrôle si votre sortie doit se produire (par exemple pour le chat).

Autres conseils

En supposant que votre fichier journal ne contienne pas les caractères de contrôle '\ 01' et '\ 02' , et qu'une ligne continue commence par exactement quatre espaces, les suivants pourrait fonctionner:

c1=`echo -en '\01'`
c2=`echo -en '\02'`
cat logfile | tr '\n' $c1 | sed "s/$c1    /$c2/g" | sed "s/$c1/\n/g" | grep cat | sed "s/$c2/\n    /g"

Explication: ceci remplace chaque nouvelle ligne par ASCII 1 (un caractère de contrôle qui ne devrait jamais figurer dans un fichier journal) et chaque séquence "newline-space-space-space-space-space". avec ASCII 2 (un autre caractère de contrôle). Il remplace ensuite ASCII 1 par des nouvelles lignes. Ainsi, chaque séquence de plusieurs lignes est placée dans une seule ligne. Les anciens sauts de ligne sont remplacés par ASCII 2. Il s’agit d’un recouvrement pour cat et les ASCII 2 sont remplacés par combinaison nouvelle-espace-espace-espace-espace.

Quelque chose comme ça?

awk 'function print_part() { if(cat) print part }  /^  / { part = part "\n" <*>; next } /cat[0-9]$/ { print_part(); part = <*>; cat = 1; next;  } { print_part(); cat=0} END { print_part() }' inputfile

L'expression rationnelle / ^ / identifie les lignes de continuation.

L'expression rationnelle / cat [0-9] $ / identifie les lignes de départ que vous souhaitez conserver.

Une autre approche consisterait à définir RS pour être autre chose que le \ n normal. Par exemple:

$ awk -v Pre=Wed 'BEGIN {RS = "\\n?\\s*" Pre} /cat.\n?/ {print Pre <*>}' file.log
Wed Nov 12 blah blah blah blah cat1
Wed Nov 12 blah blah blah blah cat2
     more blah blah
     even more blah blah
Wed Nov 12 blah blah blah blah cat3
Wed Nov 12 blah blah blah blah cat4
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top