2010-10-26 19 views
2

Je cette pour:Passage sortie d'une commande comme argument à l'autre

for i in `ls -1 access.log*`; do tail $i |awk {'print $4'} |cut -d: -f 1 |grep - $i > $i.output; done 

ls donnera access.log, access.log.1, access.log.2 etc.
queue me donnera la dernière ligne de chaque fichier, qui ressemble à: 192.168.1.23 - - [08/Oct/2010:14:05:04 +0300] etc etc etc
awk + coupe extraira la date (08/Oct/2010 - mais différent dans chaque access.log), ce qui me permettra de grep et redirige la sortie vers un fichier distinct.

Mais je n'arrive pas à passer la sortie de awk + cut à grep.

La raison de tout cela est que ces journaux d'accès incluent des lignes avec plus d'une date (06/Oct, 07/Oct, 08/Oct) et j'ai juste besoin des lignes avec la date la plus récente.

Comment puis-je y parvenir?

Merci.

+0

Pouvez-vous poster une entrée d'exemple et les résultats escomptés? –

+1

Un problème est que vous continuez d'écraser la même sortie pour chaque access.log. Notez que vous pouvez également utiliser plusieurs fichiers pour la queue. – Tomas

+0

lol .. tu as raison, je ne sais pas comment j'ai négligé ce fait. Laissez-moi y réfléchir pour que je puisse trouver une solution. – w00t

Répondre

1

titre d'observation, tail affiche les 10 dernières lignes.

Une solution possible serait de grep cette façon:

for i in `ls -lf access.log*`; do grep $(tail $i |awk {'print $4'} |cut -d: -f 1| sed 's/\[/\\[/') $i > $i.output; done 
+0

Je ne me soucie pas vraiment de cet aspect. J'aurais pu utiliser tail -n 1. – w00t

+0

@mouviciel - Je l'ai déjà essayé exactement comme vous l'avez écrit, mais cela donne grep: Unmatched [ou [^ – w00t

+0

Je vois, '[' a une signification spéciale pour 'grep'. Je modifie ma réponse. – mouviciel

0

Umm ... Utilisez xargs ou les guirlandes.

man xargs 

ou http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html, section 3.4.5. Substitution de commande

+0

Je ne vois pas comment xargs peut m'aider. Il aurait besoin de savoir quelle est la sortie de toutes les commandes précédentes, puis de la passer en tant que motif à grep. Ce ne serait pas 'commande | xargs grep 123 fichier.txt', mais ce serait 'commande | xargs grep -pattern-from-command-file.txt' – w00t

1

pourquoi ne pas le diviser en étapes ??

for file in *access.log 
do 
    what=$(tail "$i" |awk {'print $4'} |cut -d: -f 1) 
    grep "$what" "$file" >> output 
done 
+0

Ceci aussi écrase 'output' à chaque itération. –

+0

Je suppose que je peux le casser, mais je voulais l'exécuter à partir de CLI. Quoi qu'il en soit, cela a été plus d'une fois que j'avais besoin d'utiliser une fonctionnalité comme celle-ci, donc j'essaie de trouver la réponse à mon scénario. – w00t

+0

La solution élégante est de rediriger le 'done' pour écraser le fichier; de cette façon, le corps de la boucle entière est redirigé, et le fichier est ouvert pour l'écriture juste une fois, à l'intérieur de la boucle à plusieurs reprises. – tripleee

1

Vous ne devriez pas utiliser ls cette façon. En outre, ls -l vous donne des informations dont vous n'avez pas besoin. L'option -f à grep vous permettra de diriger le modèle vers grep. Toujours citer les variables qui contiennent des noms de fichiers.

for i in access.log*; do awk 'END {sub(":.*","",$4); print substr($4,2)}' "$i" | grep -f - $i > "$i.output"; done 

I a également éliminé tail et cut depuis AWK peuvent faire leur travail.

+0

Je ne vois pas de problème avec ls -l, c'est comme ça que je me suis habitué à l'utiliser. J'aurais pu utiliser ls -1, mais ce n'est pas important. AWK n'est pas un bon candidat pour le travail de tail and cut car AWK lit tout le fichier pour arriver à la fin, et quand on a 500 + mb de fichiers, cela prend trop de temps. Maintenant, à propos du grep -f, c'est vraiment utile. Merci. – w00t

+1

http://mywiki.wooledge.org/ParsingLs explique pourquoi 'ls' est problématique. – tripleee

0

vous pouvez essayer:

grep "$(stuff to get piped over to be grep-ed)" file 

Je ne l'ai pas essayé, mais ma réponse appliquée ici ressemblerait à ceci:

grep "$(for i in `ls -1 access.log*`; do tail $i |awk {'print $4'} |cut -d: -f 1 |grep - $i > $i.output; done)" $i