Dans sed ou awk, comment puis-je gérer des séparateurs d'enregistrement qui peuvent * s'étendre sur plusieurs lignes?
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
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
où 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