
Я отслеживаю файл журнала с флагом -f. Затем я передаю это в grep, чтобы найти только строки, содержащие «X». Это работает отлично. Теперь я хочу снова передать это в другой grep, который удалит все строки, содержащие «Y». Когда я добавляю второй канал, файл перестает обновляться, и похоже, что данные не поступают.
Вот команда, которая работает: tail -f my_file.log | grep "X"
Это команда, которая не делает: tail -f my_file.log | grep "X" | grep -v "Y"
Как мне это структурировать, чтобы команда работала?
решение1
Так как вывод grep
буферизован, используйте --line-buffered
опцию grep
для включения буферизации строк:
tail -f /path/to/log | grep --line-buffered 'X' | grep -v 'Y'
Если у вас grep
нет такой возможности, вы можете использовать stdbuf
в качестве альтернативы:
tail -f /path/to/log | stdbuf -oL grep 'X' | grep -v 'Y'
решение2
Обычно я нахожу более полезными awk
для такого рода логических проверок:
tail -f /path/to/log | awk '/X/ && !/Y/'
# ^^^ ^^^^
# this I want but not this
Протестировано с двумя вкладками, в одной из которых я продолжаю писать, seq 20 >> myfile
а в другой, например tail -f myfile | awk '/3/ && !/13/'
, .
решение3
Другой подход — использовать один grep
вызов вместо двух и таким образом избежать проблемы буферизации. Просто используйте регулярное выражение, которое соответствует строкам, состоящим из 0 или более не-Y символов, затем X и затем 0 или более не-Y снова до конца строки"
tail -f /path/to/log | grep '^[^Y]*X[^Y]*$'