sed или awk для удаления шаблона, включая перевод строки - PullRequest
2 голосов
/ 10 апреля 2019

У меня есть файл журнала, который был объединен со stderr, который я пытаюсь очистить.Я могу выделить и найти «загрязнение» stderr, но борюсь с одной незначительной деталью: удаление новой строки

Это отдельный стандартный вывод, который я пытаюсь восстановить:

some message 1234556
more info foo bar

и это объединенный файл stdout / stderr, от которого я пытаюсь избавиться от сообщений stderr:

some message 1234/some/path ERROR
  more info only 1 line though
556
more info foo bar

, так что это текст, от которого я пытаюсь избавиться:

/some/path ERROR
more info only 1 line though

включая символы новой строки, чтобы восстановить отдельный стандартный вывод.

Я звоню:

# get rid of the line AFTER the stderr start
sed -i".bak" -e '/ERROR/{n;d}' *.log

# get rid of the start of stderr
sed -i".bak" -r 's/\/some\/path.*ERROR//' *.log

К сожалению, теперь вывод:

some message 1234
556
more info foo bar

Примечаниеточка вставки сообщения stderr может быть произвольной (в середине строки или в начале, где угодно).Единственное, что я могу предположить, это то, что stderr является двухстрочным и начинается с /some/path и содержит идентификатор ошибки (ERROR или что-то еще).Кроме того, может быть несколько последующих сообщений stderr, таких как:

some message 1234/some/path ERROR
  more info only 1 line though
/some/path ANOTHER_ERR
  more info only 1 line though
556
more info foo bar

, которые, я думаю, не представляют большой проблемы (есть только 2 вида, поэтому я могу запустить несколько разных совпадений (ERRORи ANOTHER_ERR)).Мне также все равно, какой инструмент используется sed или awk ...

Ответы [ 4 ]

4 голосов
/ 10 апреля 2019

Вы можете использовать опцию мощного режима абзаца perl. Параметр командной строки -00, который включает режим создания абзаца, то есть Perl читает текст абзац за абзацем, а не построчно (абзац - это текст между двумя или более символами новой строки.)

perl -00 -pe 's/\/.*(ERROR|ANOTHER_ERR)\n.*\n//g' file

Чтобы добавить модификацию на месте, добавьте флаг -i, аналогично sed

perl -00 -pi -e 's/\/.*(ERROR|ANOTHER_ERR)\n.*\n//g' file
3 голосов
/ 10 апреля 2019

С GNU sed для -E и -z:

$ sed -Ez 's:/some/path ERROR\n[^\n]+\n::g' file
some message 1234556
more info foo bar

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

$ cat file
some message 1234/some/path ERROR
  more info only 1 line though
/some/path ANOTHER_ERR
  more info only 1 line though
556
more info foo bar

$ sed -Ez 's:/some/path (ERROR|ANOTHER_ERR)\n[^\n]+\n::g' file
some message 1234556
more info foo bar

В качестве альтернативы, с GNU awk для RS с несколькими символами:

$ awk -v RS='/some/path ERROR\n[^\n]+\n' -v ORS= '1' file
some message 1234556
more info foo bar

или, если вы предпочитаете:

$ awk -v RS='^$' -v ORS= '{gsub("/some/path ERROR\n[^\n]+\n","")}1' file
some message 1234556
more info foo bar
2 голосов
/ 10 апреля 2019

Кажется, идеально подходит для некоторых основных сед.Просто используйте N, чтобы проглотить следующую строку в пространстве образца.

sed '/ERROR/{N;s/\/.*//;N;s/\n//g}' input.log

  • N Добавить следующую строку в пространство образца
  • Удалитьвсе после косой черты (включая следующую строку)
  • N Добавить следующую строку к пробелу
  • Удалить все разрывы строк

Это недалеко от ОПпопытки с n.

Чтобы расширить это до более позднего примера, вы вернетесь назад к началу, чтобы посмотреть, принесли ли команды N больше строк ошибок в пространство образца:

sed -E ':a /(ERROR|ANOTHER_ERR)/{N;s/\/.*//;N;s/\n//g;b a}'

  • Используйте -E, чтобы разрешить использование двух шаблонов в паренах
  • Добавьте метку :a
  • b a в ответ на :a всякий раз, когдастрока ошибки в пространстве образца найдена и обработана.

Я предпочитаю избегать sed -z.Он будет считывать весь файл в пространство шаблонов, поэтому он может оказаться не лучшим выбором, если этот файл журнала длинный или вы направляете активный поток в sed.

1 голос
/ 10 апреля 2019

Другое решение sed без опции -z:

$ sed -E -n '/ERROR/{s@/.*@@;h;n;n;H;n;H;x;s/\n//;p}' input.log
some message 1234556
more info foo bar
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...