Вот решение awk
которое упрощает вещи, обрабатывая вывод в обратном порядке (требуется команда tac
, которая является частью GNU coreutils):
Во-первых, скрипт awk
(помещается в файл, такой как 'process.awk'). Это слишком много для однострочной игры bash
.
BEGIN { output=0; any=0; }
/^Test .* FAILED/ { output=1; any=1; }
/^Test .* PASSED/ { output=0; }
/^Start test group/ && any == 1 { output=1; any=0; }
output == 1 { print; }
Затем запустите этот сценарий в обратном файле журнала и сторнируйте вывод:
tac logfile | awk -f process.awk | tac
Как это работает?
Сначала мы передаем наш ввод через tac
, чтобы изменить порядок строк (чтобы мы могли определить, принадлежат ли "следующие" строки тесту FAILED или PASSED, прежде чем их читать).
Сценарий работает следующим образом. Каждое действие состоит из условия, которое должно быть сопоставлено, за которым следует блок кода для выполнения, если текущая строка соответствует условию.
Первое действие - это действие BEGIN, которое всегда выполняется один раз, прежде чем мы начнем смотреть на вход. Он инициализировал два логических флага, которые управляют тем, что печатается. output
будет установлен в 1, если мы хотим напечатать текущую строку, в противном случае 0. any
будет установлен в 1 каждый раз, когда мы сталкиваемся с ошибочным тестом, и сбрасывается в 0 после того, как мы закончили обработку группы тестов. Оба значения начинаются с 0.
Следующее действие проверяет текущую строку, чтобы увидеть, является ли она началом неудачного теста (помните, мы обрабатываем вывод в обратном порядке). Если это так, установите оба output
и any
.
Следующее действие проверяет текущую строку, чтобы увидеть, является ли она началом пройденного теста. Если это так, снимите флаг output
но оставляй в одиночку. (До конца тестовой группы все еще может быть неудачный тест).
Следующее действие проверяет текущую строку, чтобы увидеть, является ли она заголовком группы тестирования и установлен ли флаг any
. Если это так, мы хотим напечатать заголовок (у нас был хотя бы один неудачный тест), поэтому установите output
и очистите any
(чтобы подготовиться к следующей группе тестов). В противном случае нам ничего не нужно делать; any
уже равен 0, и output
не может быть установлен в 1
если any
никогда не было.
Наконец, у нас есть действие, которое не смотрит на текущую строку, а просто проверяет, установило ли какое-либо из предыдущих действий output
. Если они есть, мы печатаем текущую строку (которая может быть строкой "Test FAILED", некоторой подробной информацией, которая "предшествует" строке FAILED, или заголовком группы тестов).
Когда все действия исчерпаны, мы переходим к следующей строке ввода и пытаемся применить каждое действие снова. После того, как все входные данные исчерпаны, мы напечатаем каждую из выходных строк, которые мы хотим, но в обратном порядке. Трубопровод вывода через tac
исправляет это.
Обратите внимание, что скрипт можно сделать немного более эффективным за счет усложнения, но он должен быть достаточно быстрым.