AWK如何定义线?

时间:2018-12-12 21:21:23

标签: regex logging awk

我试图使用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 :(得分:3)

你在做。

awk '/^\[/{p=/WC_BUSINESSCO/}p' test.log
  • /^\[/表示如果当前记录以{...}开头,请执行以下操作([
  • 如果当前记录包含p=/WC_BUSINESSCO/
  • pWC_BUSINESSCO设置为true,反之亦然,
  • p结尾意味着如果p为true,则打印当前记录。
  • 如果当前行不是 [开头,则上一个行中的p值仍然保留。

有关更多信息,请参见man awk

为清楚起见,请增加一些空白:

awk '
    /^\[/ { p = /WC_BUSINESSCO/ }
    p
' test.log

答案 1 :(得分:2)

awk如何定义行?

Awk不知道行是什么。 Awk知道 records fields 的概念。

文件被拆分为 records ,其中连续记录由记录分隔符RS拆分。每个记录都分为多个字段,其中连续的字段由字段分隔符FS分隔。

默认情况下,记录分隔符RS设置为字符(\n),因此每个记录都是一行。记录分隔符具有以下定义:

  

RS   字符串值RS的第一个字符应为输入记录分隔符;默认情况下为。如果RS包含多个字符,则结果不确定。如果RS为空,则记录由由加上一个或多个空行组成的序列分隔,开头或结尾的空行在输入的开头或结尾不应导致空记录,并且不管FS的值是什么,都应该始终是字段分隔符。

我现在如何定义多行记录?

对于不能由单个字符唯一标识记录开始的多行记录,您可能要使用gawkRS可以是多个字符的任何awk版本(或正则表达式)。对于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,第一行可能就足够了。更一般的问题可能与此有关。    

答案 2 :(得分:1)

您说的是:然后打印出该行,并打印以下行

尝试以下方法:

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

当模式匹配时,流程非常简单,打印一行,获取下一行并再次打印。

要获取以[开头的行之后的所有行:

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

选中this

答案 3 :(得分:1)

使用GNU-awk,您可以根据指定的内容定义记录分隔符

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

使用模式匹配打印记录(可能是多行),但记录分隔符以记录为前缀。

与其他awk的解决方法

$ awk '/^\[/{if(/WC_BUSINESSCO/){print; p=1} else p=0} p&&!/^\[/' file

答案 4 :(得分:0)

如果您正在考虑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>