Удалите все строки с середины строки, соответствующей строке, пока второе строковое соответствие не будет найдено

Я пытаюсь удалить сообщения об ошибках, распечатанные в мой файл. У меня есть это:

 addr:1122c:1234:
 addr:11230:5678:
 addr:11223:01Error:abcdef(x, y) = z, value = a
Error:hijklm(v, q) = w, value = b
Error:nopqrst(x, y) = z, value = d
Error:uvwxyz(l, m) = z, value = e
Error:1234(u, t) = z, value = f
Error:567(r, s) = z, value = g
err_total = 9846, err_sub = 0, err_mask = 239
1 Duration: xyz, abc
0 Duration: pqr, def
23:
 addr:11238:4567:
 addr:1123c:8901:

Я должен удалить все сообщения об ошибках до следующего addr, появляется. Необходимый вывод:

 addr:1122c:1234:
 addr:11230:5678:
 addr:11223:0123:
 addr:11238:4567:
 addr:1123c:8901:

Я попробовал:

sed -i "/\bError\b/d" file_name

Но это удаляет строки, начинающие с Ошибки, и не удалило строку где Строка ошибки, запущенная с середины.

Я плохо знаком с регулярными выражениями, explaination был бы действительно полезен.

Править: Я использую sed -i '/Error/,/addr/d' filename но это удаляет целую строку и не дает то, что я ищу.

3
задан 8 August 2018 в 12:27

3 ответа

sed не действительно хорошо в Многострочном Соответствии.
Можно обмануть его, чтобы сделать то, что Вы хотите, но затем imo perl легче обработать.

Попробуйте это:

perl -pe 'BEGIN{undef $/;}; s/Error.*?(^[0-9]* Duration: [^\n]*\n)+//smg;'

Объяснение:

  • BEGIN { do_something; }: Сделайте что-то однажды вначале
  • undef $/: Проигнорируйте окончания строки
  • s/// Замена
  • Error.* Соответствуйте любой строке, начинающейся с "Ошибки".
  • ? Сделайте предыдущее соответствие нежадным, для которого оно останавливается в следующем соответствии или в этой группе соответствия случая...
  • ()+ Сделайте группу соответствия, которая должна быть подобрана, по крайней мере, однажды (+).
  • ^[0-9]* Duration: [^\n]*\n: Соответствуйте целой строке Продолжительности включительно

(через)

4
ответ дан 1 December 2019 в 13:22

Это сгенерирует результат, который вы искали:

$ cat file_name | grep -v \
    -e '^Error:' \
    -e '^err_total' \
    -e '^.*[0-9] Duration:' | \
    sed ':a;$!N;s/Error:.*\n\(.*[0-9]\):/\1:/;ta;P;D'

Frist удалите все вещи Error, err_total и 12345 Duration:. Затем найдите Error: ..., прерывающий ваш вывод, удалите новую строку (\n), найдите следующий вхождение числа (.*[0-9]:) и добавьте его к текущей строке.

1
ответ дан 1 December 2019 в 13:22

Вместо того, чтобы удалять"Error:"строки, почему бы не извлечь просто строки Вы хотите с:

grep -E '^ addr:' file_name | sed -e 's/Error:.*//'
2
ответ дан 1 December 2019 в 13:22

Другие вопросы по тегам:

Похожие вопросы: