Как AWK определяет линию? - PullRequest
       7

Как AWK определяет линию?

0 голосов
/ 13 декабря 2018

Я пытался проанализировать файл журнала, используя AWK,

test.log

[12/12/18 11:54:54:321 PST] 0000077c WC_SERVER     < com.ibm.commerce.server.HttpRequestWrapper setAttribute(String,Object) Exit
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO < -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextserviceimpl.BusinessContextServiceImpl.createContextSPI(ActivityToken, ActivityData, String) Exit
                                 com.ibm.commerce.context.base.BaseContext : [bInitialize = false][bRecalibrate = false][inCallerId = null][inRunAsId = null][inStoreId = null][istrChannelId = null][bDirty = false][bRequestStarted = false][iOriginalSerializedString = null][iToken = null]
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO > -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextserviceimpl.BusinessContextServiceImpl.loadContextData(ActivityToken, String) Entry
                                 68884:false:false:0
                                 com.ibm.commerce.context.base.BaseContext
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO > -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextservice.commands.ContextDataSerValueCacheCmdImpl.myPerformExecute() Entry
                                 68884

Идея в том, что если строка начинается с [ и соответствует шаблону, затем распечатайте строку, а также следующую строку, которая не начинается с [.

Ожидаемый результат:

[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO < -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextserviceimpl.BusinessContextServiceImpl.createContextSPI(ActivityToken, ActivityData, String) Exit
                                 com.ibm.commerce.context.base.BaseContext : [bInitialize = false][bRecalibrate = false][inCallerId = null][inRunAsId = null][inStoreId = null][istrChannelId = null][bDirty = false][bRequestStarted = false][iOriginalSerializedString = null][iToken = null]
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO > -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextserviceimpl.BusinessContextServiceImpl.loadContextData(ActivityToken, String) Entry
                                 68884:false:false:0
                                 com.ibm.commerce.context.base.BaseContext
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO > -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextservice.commands.ContextDataSerValueCacheCmdImpl.myPerformExecute() Entry
                                 68884

AWK:

awk 'BEGIN{IGNORECASE = 1; flag = 0;}{ if($0 ~ /^\[/){if($0 ~ /WC_BUSINESSCO/){flag=1}else{flag = 0}; if(flag==1){print $0}}}' test.log

Текущий вывод:

[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO < -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextserviceimpl.BusinessContextServiceImpl.createContextSPI(ActivityToken, ActivityData, String) Exit
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO > -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextserviceimpl.BusinessContextServiceImpl.loadContextData(ActivityToken, String) Entry
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO > -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextservice.commands.ContextDataSerValueCacheCmdImpl.myPerformExecute() Entry

Как видите, строки, которые не начинаются с [, не печатаются;после некоторой отладки, похоже, что AWK считает, что строки вопроса - это часть или линия, соответствующая шаблону.Я полагаю, это не распечатка из-за проблемы с переносом.

Как это исправить?

Ответы [ 5 ]

0 голосов
/ 14 декабря 2018

Как awk определяет линию?

Awk не знает, что такое линия.Awk знает концепцию records и fields .

Файлы разбиты на records , где последовательные записи разделяются разделителем записей RS.Каждая запись разделяется на поля, где последовательные поля разделяются разделителем полей FS.

По умолчанию разделитель записей RS устанавливается на символ (\n) итаким образом, каждая запись является строкой.Разделитель записей имеет следующее определение:

RS: Первый символ строкового значения RS должен быть разделителем входных записей; по умолчанию.Если RS содержит более одного символа, результаты не указываются.Если RS равно нулю, то записи разделяются последовательностями, состоящими из плюс одна или несколько пустых строк, начальные или конечные пустые строки не должны приводить к пустым записям в начале или конце ввода, а всегда должен быть разделителем полей, независимо от значения FS.

Как теперь определить многострочную запись?

Для многострочных записей, где начало записи не может быть однозначно идентифицировано одним символом, вы можете использовать gawk или любую версию awk, где RS может быть несколькими символами (или регулярным выражением),В случае OP вы можете определить RS как \n\[:

awk 'BEGIN { RS="\n\[" }/WC_BUSINESSCO/ { print (NR==1 ? "" : "[") $0 }' file

Если у вас нет доступа к такой версии awk, и вам нужно придерживаться POSIX, вы можете сделать:

awk '/^\[/ && (rec ~ /WC_BUSINESSCO/) { printf rec; } # process record
     /^\[/ { rec="" }                                 # initialise record
     { rec = rec $0 ORS }                             # build record
     END { if (rec ~ /WC_BUSINESSCO/) printf rec }    # process last record
    ' file

Это будет соответствовать "WC_BUSINESSCO" в полной записи, а не только первой строке, как это делается в большинстве решений здесь.В то время как для OP первой строки может быть достаточно.Более общие вопросы могут иметь проблемы с этим.

0 голосов
/ 13 декабря 2018

Если вы рассматриваете Perl, то это общее решение, основанное на ваших требованиях.Обратите внимание, что он не жестко кодирует текст (например, WC_BUSINESSCO) из файла для решения.

/tmp> cat test.log
[12/12/18 11:54:54:321 PST] 0000077c WC_SERVER     < com.ibm.commerce.server.HttpRequestWrapper setAttribute(String,Object) Exit
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO < -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextserviceimpl.BusinessContextServiceImpl.createContextSPI(ActivityToken, ActivityData, String) Exit
                                 com.ibm.commerce.context.base.BaseContext : [bInitialize = false][bRecalibrate = false][inCallerId = null][inRunAsId = null][inStoreId = null][istrChannelId = null][bDirty = false][bRequestStarted = false][iOriginalSerializedString = null][iToken = null]
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO > -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextserviceimpl.BusinessContextServiceImpl.loadContextData(ActivityToken, String) Entry
                                 68884:false:false:0
                                 com.ibm.commerce.context.base.BaseContext
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO > -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextservice.commands.ContextDataSerValueCacheCmdImpl.myPerformExecute() Entry
                                 68884
/tmp> perl -ne ' print "$t$p" if $x and /^\[/ ;if(!/^\[/) { $x++;$t.=$p} if(/^\[/) { $x=0;$t=""} $p=$_;END { print "$t$p" if $x }' test.log
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO < -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextserviceimpl.BusinessContextServiceImpl.createContextSPI(ActivityToken, ActivityData, String) Exit
                                 com.ibm.commerce.context.base.BaseContext : [bInitialize = false][bRecalibrate = false][inCallerId = null][inRunAsId = null][inStoreId = null][istrChannelId = null][bDirty = false][bRequestStarted = false][iOriginalSerializedString = null][iToken = null]
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO > -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextserviceimpl.BusinessContextServiceImpl.loadContextData(ActivityToken, String) Entry
                                 68884:false:false:0
                                 com.ibm.commerce.context.base.BaseContext
[12/12/18 11:54:54:328 PST] 0000077c WC_BUSINESSCO > -1112ef1b:16732963f15:-7fd4 com.ibm.commerce.component.contextservice.commands.ContextDataSerValueCacheCmdImpl.myPerformExecute() Entry
                                 68884
/tmp>
0 голосов
/ 13 декабря 2018

Вы переусердствовали.

awk '/^\[/{p=/WC_BUSINESSCO/}p' test.log
  • /^\[/ означает выполнение следующего действия ({...}), если текущая запись начинается с [,
  • p=/WC_BUSINESSCO/ устанавливает p true, если текущая запись содержит WC_BUSINESSCO, и наоборот,
  • p в конце означает печать текущей записи, если p истинно.
  • , еслитекущая строка не начинается с [, затем сохраняется значение p из предыдущей строки .

Для получения дополнительной информации см. man awk.

Для ясности, некоторые дополнительные пробелы:

awk '
    /^\[/ { p = /WC_BUSINESSCO/ }
    p
' test.log
0 голосов
/ 13 декабря 2018

с помощью GNU- awk вы можете определить разделитель записей, как вы указали

$ awk -v RS='(^|\n)\\[' '/WC_BUSINESSCO/{print RT $0}' file

с помощью сопоставления с шаблоном печати записи (возможно, многострочный), но с разделителем записи с префиксом к записи

с другими awk s обходным путем

$ awk '/^\[/{if(/WC_BUSINESSCO/){print; p=1} else p=0} p&&!/^\[/' file
0 голосов
/ 13 декабря 2018

Вы сказали: затем распечатайте строку и также следующую строку .

Попробуйте вместо этого:

awk '/^\[.*WC_BUSINESSCO/{print;getline;print}' test.log

Потокдовольно просто, когда шаблон совпадает, выведите следующую строку и напечатайте снова.

Чтобы получить все строки после той, которая начинается с [:

awk '/^\[/{i=0}/WC_BUSINESSCO/{i=1}i' test.log

Проверьте это .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...