Je termine un fichier journal avec l'option -f. Ensuite, je passe ceci à grep, pour ne trouver que les lignes contenant "X". Cela fonctionne parfaitement bien. Maintenant, je veux diriger ceci à nouveau dans un autre grep, qui supprimera toutes les lignes contenant "Y". Lorsque j'ajoute le deuxième canal, le fichier cesse de se régénérer et il semble qu'aucune donnée ne vienne.
C'est la commande qui fonctionne: tail -f my_file.log | grep "X"
C'est la commande qui ne le fait pas: tail -f my_file.log | grep "X" | grep -v "Y"
Comment dois-je structurer cela pour que la commande fonctionne?
Comme la sortie de grep
est mise en mémoire tampon, utilisez l'option --line-buffered
de grep
pour activer la mise en mémoire tampon des lignes:
tail -f /path/to/log | grep --line-buffered 'X' | grep -v 'Y'
Si votre grep
ne dispose pas de cette option, vous pouvez utiliser stdbuf
comme alternative:
tail -f /path/to/log | stdbuf -oL grep 'X' | grep -v 'Y'
Je trouve normalement plus utile awk
pour ce type de vérification logique:
tail -f /path/to/log | awk '/X/ && !/Y/'
# ^^^ ^^^^
# this I want but not this
Testé en ayant deux onglets, l'un dans lequel je continue d'écrire seq 20 >> myfile
et l'autre ayant par exemple tail -f myfile | awk '/3/ && !/13/'
.
Une autre approche consisterait à utiliser une seule invocation grep
au lieu de deux et à éviter le problème de mise en mémoire tampon. Utilisez simplement une expression régulière qui correspond aux lignes composées de 0 ou plusieurs caractères non-Y, puis un X et ensuite 0 ou plusieurs non-Y à nouveau jusqu'à la fin de la ligne "
tail -f /path/to/log | grep '^[^Y]*X[^Y]*$'