sed — удалите несколько строк, если они заканчиваются на «не удается найти метку».

#regex #sed

Вопрос:

У меня очень большой файл журнала (более 2 ГБ), и я хотел бы удалить все журналы отладки, если они содержат «EntityFramework».

 info: Microsoft.EntityFrameworkCore.Migrations[20405]
      No migrations were applied. The database is already up to date.
dbug: Microsoft.EntityFrameworkCore.Infrastructure[10407]
      'IDCDbContext' disposed.
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
info: Hangfire.PostgreSql.PostgreSqlStorage[0]
      Start installing Hangfire SQL objects...
 

Здесь я хотел бы удалить журнал ниже и сохранить остальные

 dbug: Microsoft.EntityFrameworkCore.Infrastructure[10407]
      'IDCDbContext' disposed.
 

То, что я пробовал до сих пор:

 sed -i '/^dbug/{:b,N;/^[[:lower:]]/!bb};/.*EntityFramework.*/d' logs
 

Однако это приводит к sed: can't find label for jump to b'

Есть идеи?

Ответ №1:

Эта работа лучше подходит для awk :

 awk '!p || !/^[[:blank:]]/ {p = /^dbug:/} !p' file

info: Microsoft.EntityFrameworkCore.Migrations[20405]
      No migrations were applied. The database is already up to date.
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
info: Hangfire.PostgreSql.PostgreSqlStorage[0]
      Start installing Hangfire SQL objects...
 

Мы сохраняем флаг p , чтобы контролировать, печатать его или нет. p устанавливается в 1 положение, когда строка начинается с /dbug:/ и остается установленной для следующих строк dbug: , которые начинаются с пробелов.

Ответ №2:

Текущая ошибка связана с запятой после b метки, должна быть точка с запятой. Кроме того, вы должны включить /.*EntityFramework.*/d (или лучше /EntityFramework/d включить ) в командный блок, чтобы он выполнялся только внутри него:

 sed -i '/^dbug/{:b;N;/^[[:lower:]]/!bb;/EntityFramework/d}' logs
 

Смотрите онлайн-демонстрацию.

Ответ №3:

1-е решение: С показанными вами образцами, пожалуйста, попробуйте следующую awk программу, написанную и протестированную в GNU awk . Простым объяснением было бы использование awk match функции ‘s для сопоставления регулярных ndbug:[^n]*n[^n]* выражений и печать только тех строк, которые требуются для вывода OP(только не совпадающие строки).

 awk -v RS= 'match($0,/ndbug:[^n]*n[^n]*/){print substr($0,1,RSTART-1) substr($0,RSTART RLENGTH)}' Input_file
 

2-е решение: Использование возможности разделителя записей awk и печать соответствующих значений, необходимых для OP.

 awk -v RS='ndbug:[^n]*n[^n]*n' '{gsub(/n $/,"")}1' Input_file