Aide sur les scripts Awk - Problème de logique
Question
Je suis en train d'écrire un simple script .sh pour analyser un fichier journal Exim pour les chaînes correspondant à " o '" ;. Actuellement, lors de l’affichage du fichier output.txt, il n’ya que 0 imprimé sur chaque ligne (606 lignes). Je suppose que ma logique est fausse, car awk ne renvoie aucune erreur.
Voici mon code (mis à jour pour les problèmes de concaténation et de compteur). Edit: J'ai adopté un nouveau code issu de la réponse de dmckee avec laquelle je travaille maintenant sur l'ancien code en faveur de la simplicité.
awk '/o'\''/ {
line = "> ";
for(i = 20; i <= 33; i++) {
line = line " " $i;
}
print line;
}' /var/log/exim/main.log > output.txt
Des idées?
EDIT: Par souci de clarté, je cherche "& o;" dans les adresses e-mail, car 'est un caractère illégal dans les adresses e-mail (et dans nos bases de données, apparaît uniquement avec des noms avec un préfixe «o»).
EDIT 2: conformément à la demande de commentaire, voici un exemple précis de la sortie souhaitée:
[xxx.xxx.xxx.xxx] kathleen.o'toole@domain.com <kathleen.o'toole@domain.com> routing defer (-51): retry time not reached
[xxx.xxx.xxx.xxx] julie.o'brien@domain.com <julie.o'brien@domain.com> routing defer (-51): retry time not reached
[xxx.xxx.xxx.xxx] james.o'dell@domain.com <james.o'dell@domain.com> routing defer (-51): retry time not reached
[xxx.xxx.xxx.xxx] daniel_o'leary@domain.com <aniel_o'leary@domain.com> routing defer (-51): retry time not reached
La raison pour laquelle je commence à 20 dans ma boucle est parce que tout ce qui précède le 20e champ ne sont que des informations de journal standard qui ne sont pas nécessaires à mes fins ici. Tout ce dont j'ai besoin, c'est de l'adresse IP et au-delà pour cette solution (les messages pour chaque erreur 550 sont différents pour chaque serveur de messagerie utilisé. Je suis en train de compiler une liste des plus courants)
La solution
Le grep n’est pas vraiment nécessaire ici. Laissez awk sélectionner les lignes qui vous conviennent (et corrigez le bogue de concaténation comme décrit dans les notices & # 932; & # 937; & # 932; & # 918; & # 921; & # 927; & # 933;):
awk '/o'\''/ {
line = "> ";
for(i = 20; i <= 33; i++) {
line = line " " $i;
}
print line;
}' /var/log/exim/main.log > output.txt
Bien sûr, vous finirez par avoir besoin de s'échapper bizarrement si vous le faites au balai, comme ci-dessus. C'est plus propre dans un script ...
Modifier: lors du premier passage, j'ai raté le problème + = ...
Supposons également que la ligne que vous avez indiquée ci-dessus est partielle, car elle ne comporte que 13 champs (les champs sont par défaut délimités par des espaces).
Autres conseils
+
signifie l'addition numérique dans awk. Si vous souhaitez concaténer, placez simplement les constantes et / ou expressions séparées par des espaces.
Donc, ce
line += " " + $i
devrait devenir
line = line " " $i
EDIT: Iff Les fichiers journaux exim (je suis plus dans Postfix :) sont séparés par un seul espace, les éléments suivants ne sont-ils pas plus simples:
grep -F o\' /var/log/exim/main.log | cut -d\ -f20-33 >output.txt
?
" '" n'est pas illégal dans les parties locales. Dans la RFC2821 , section 4.1.2:
Local-part = Dot-string / Quoted-string
Dot-string = Atom *("." Atom)
Atom = 1*atext
2821 références supplémentaires RFC2822 pour les éléments non définis localement, ainsi:
atext = ALPHA / DIGIT / ; Any character except controls,
"!" / "#" / ; SP, and specials.
"<*>quot; / "%" / ; Used for atoms
"&" / "'" /
"*" / "+" /
"-" / "/" /
"=" / "?" /
"^" / "_" /
"`" / "{" /
"|" / "}" /
"~"
En d'autres termes, "&"; est un parfaitement légal non caraculé à avoir dans un email localpart. Il se peut que ce ne soit pas légal sur votre site , mais ce n'est pas ce que vous avez dit.
Désolé de ne pas rester directement sur le sujet, mais je voulais corriger votre affirmation.
Tâche éteinte et encore plus simple: python.
import fileinput
for line in fileinput.input():
if "'" in line:
fields = line.split(' ')
print "> ", ' '.join( fields[20:34] )