用部分可选的内容来抓取一段文本


8

我在一个非常大的日志文件(例如A.log)中描述了一个事件的多个条目。我想对日志文件中的事件条目做两件事:

  1. 计算每个此类条目的出现次数(这不是强制性要求,但是很高兴拥有)。
  2. 将实际条目提取到一个单独的文件中,并在以后进行研究。

典型的事件条目如下所示,并且它们之间还会有其他文本。因此,在下面的示例中,有两个事件条目,第一个包含两个DataChangeEntry 有效负载,第二个包含一个DataChangeEntry 有效负载。

    Data control raising event :DataControl@263c015d[[
    #### DataChangeEvent #### on [DataControl name=PatternMatch_LegendTimeAxis, binding=.dynamicRegion1.                         beam_project_PatternMatch_dashboard_LegendTimeAxis_taskflow_LegendTimeAxis_beamDashboardLegendTimeAxisPageDef_beam_project_PatternMatch_dashboard_LegendTimeAxis_taskflow_LegendTimeAxis_beamDashboardLegendTimeAxis_xml_ps_taskflowid.dynamicRegion58.                                                                                                                         beam_project_PatternMatch_view_LegendTimeAxis_taskflow_LegendTimeAxis_beamVizLegendTimeAxisPageDef_beam_project_PatternMatch_view_LegendTimeAxis_taskflow_LegendTimeAxis_beamVizLegendTimeAxis_xml_ps_taskflowid.QueryIterator]
    Filter/Collection Id : 0
    Collection Level     : 0
    Sequence Id             : 616
    ViewSetId            : PatternMatch.LegendTimeAxis_V1_0_SN49
    ==== DataChangeEntry (#1)
    ChangeType           : UPDATE
    KeyPath              : [2014-06-26 06:15:00.0, 0]
    AttributeNames       : [DATAOBJECT_CREATED, COUNTX, QueryName]
    AttributeValues      : [2014-06-26 06:15:00.0, 11, StrAvgCallWaitTimeGreaterThanThreshold]
    AttributeTypes       : [java.sql.Timestamp, java.lang.Integer, java.lang.String,  ]
    ==== DataChangeEntry (#2)
    ChangeType           : UPDATE
    KeyPath              : [2014-06-26 06:15:00.0, 0]
    AttributeNames       : [DATAOBJECT_CREATED, COUNTX, QueryName]
    AttributeValues      : [2014-06-26 06:15:00.0, 9, AverageCallWaitingTimeGreateThanThreshold]
    AttributeTypes       : [java.sql.Timestamp, java.lang.Integer, java.lang.String,  ]

    ]]

someother non useful text
spanning multiple lines 

 Data control raising event :DataControl@263c015d[[
    #### DataChangeEvent #### on [DataControl name=PatternMatch_LegendTimeAxis, binding=.dynamicRegion1.                         beam_project_PatternMatch_dashboard_LegendTimeAxis_taskflow_LegendTimeAxis_beamDashboardLegendTimeAxisPageDef_beam_project_PatternMatch_dashboard_LegendTimeAxis_taskflow_LegendTimeAxis_beamDashboardLegendTimeAxis_xml_ps_taskflowid.dynamicRegion58.                                                                                                                         beam_project_PatternMatch_view_LegendTimeAxis_taskflow_LegendTimeAxis_beamVizLegendTimeAxisPageDef_beam_project_PatternMatch_view_LegendTimeAxis_taskflow_LegendTimeAxis_beamVizLegendTimeAxis_xml_ps_taskflowid.QueryIterator]
    Filter/Collection Id : 0
    Collection Level     : 0
    Sequence Id             : 616
    ViewSetId            : PatternMatch.LegendTimeAxis_V1_0_SN49
    ==== DataChangeEntry (#1)
    ChangeType           : UPDATE
    KeyPath              : [2014-06-26 06:15:00.0, 0]
    AttributeNames       : [DATAOBJECT_CREATED, COUNTX, QueryName]
    AttributeValues      : [2014-06-26 06:15:00.0, 11, StrAvgCallWaitTimeGreaterThanThreshold]
    AttributeTypes       : [java.sql.Timestamp, java.lang.Integer, java.lang.String,  ]

    ]]

请注意,==== DataChangeEntry事件条目中的行数 可以变化。也可能完全不存在,这将指示空事件有效负载,并且是错误情况,并且肯定也想抓住这种情况。

由于在这种情况下,条目的输出跨多行,因此使用普通香草grep并不会太远。因此,我正在寻求专家意见。

PS:

  1. 让我更明确地说明我的要求。我想逐字捕获上面显示的整个文本块,并可以选择计算遇到的此类块的实例数。计算实例数量的选项很好,但不是强制性要求。
  2. 如果问题的解决方案是使用awk,我想保存awk文件并重新使用它。因此,请同时提及执行脚本的步骤。我知道regex和grep,但对sed和/或awk不熟悉。

他们总是从头开始Data control raising event吗?
LatinSuD 2014年

@LatinSuD是的,它始终以该字符串开头。
极客

我认为这是awk的工作,使用“状态机”变量,但是您应该添加一些更多信息以获取帮助,例如搜索的确切令牌以及您期望的最终结果。
Didi Kohen

@DavidKohen 事件条目以“数据控件引发事件”标记开头,并以新行结尾的“]]”结束。我想找出每个这样的事件实例。
极客

找到他们呢?算他们的数量?全部打印吗?请编辑您的问题并添加示例预期输出(最好使用不同的示例输入)。
Didi Kohen 2014年

Answers:


4

我希望这样做。事件已events归档。消息发送到标准输出。

将此文件保存到myprogram.awk中(例如):

#!/usr/bin/awk -f

BEGIN {
   s=0;  ### state. Active when parsing inside an event
   nevent=0;  ### Current event number
   printf "" > "events"
}

# Start of event
/^ *Data control raising event/ {
   s=1;
   dentries=0;
   print "*** Event number: " nevent >> "events"
   nevent++
}

# Standard event line
s==1 {
   print >> "events"
}

# DataChangeEntry line
/^ *==== DataChangeEntry/ {
   dentries ++
}

# End of event
s==1 && /^ *\]\]/ {
   s=0;
   print "" >> "events"
   if(dentries==0){
      print "Warning: Event " nevent " has no Data Entries"
   }
}

END {
   print "Total event count: " nevent
}

您可以通过不同的方式调用它:

  • myprogram.awk inputfile.txt
  • awk -f myprogram.awk inputfile.txt

样本输出:

Warning: Event 3 has no Data Entries
Total event count: 3

您可以events在工作目录中的文件中一起检查所有事件。


您应该将事件计数器与事件标头分开增加(或在操作符之前加上),这将导致标头和页脚显示不同的数字,并且可读性较低。
Didi Kohen 2014年

@LatinSuD我对awk不熟悉。因此,如果您可以添加运行上述程序所需的部分,将非常有帮助。对我来说,输入文件是A.log
极客

要使用此脚本,只需将inputfile.txt替换为您的文件名,或者更好的方法是,删除目录和管道,并将文件名放在单引号后。
Didi Kohen

@DavidKohen我想保存此脚本。因此,如果我将其保存为findEvents.awk。我可以这样执行awk -f findEvents.awk A.log吗?
极客2014年

您可以,但是您应该只将部分保存在该文件的单引号中。
Didi Kohen 2014年

2

一个非常简单的方法是

awk '{print > NR".entry"}END{print NR" entries"}' RS="]]" file 

这将为每个条目创建一个单独的文件,并将找到的条目数量打印到标准输出中。

说明

  • NR是中的当前行号awk
  • RS="]]"将记录分隔符(定义为“行”)设置为]]。这意味着每个条目将被当作一行awk
  • {print > NR".entry"}:这会将当前行(条目)打印到名为的文件中[LineNumber].entry。因此,1.entry将包含第一个,2.entry第二个,依此类推。
  • END{print NR" entries"}:处理完整个输入文件后,将执行END块。因此,此时NR将处理的条目数。

您可以将其另存为别名,也可以将其放入脚本中,如下所示:

#!/usr/bin/env bash
awk '{print > NR".entry"}END{print NR" entries"}' RS="]]" "$1"

然后foo.sh,将目标文件作为参数运行脚本(假设它已被调用并在$ PATH中):

foo.sh file

您也可以调整输出文件名。例如,要调用文件,请[date].[entry number].[entry]改用以下命令:

#!/usr/bin/env bash
date=$(date +%Y%m%d)
awk '{print > d"."NR".entry"}END{print NR" entries"}' RS="]]" d="$date" "$1"

以上假设您的日志文件仅由“事件”条目组成。如果不是这种情况,并且您可以有其他行,并且应忽略这些行,请改用此命令:

 #!/usr/bin/env bash
date=$(date +%Y%m%d)
awk '{
        if(/\[\[/){a=1; c++;}
        if(/\]\]/){a=0; print > d"."c".entry"}
        if(a==1){print >> d"."c".entry"}
}' d="$date" file 

或者,作为单线:

awk '{if(/\[\[/){a=1; c++;}if(/\]\]/){a=0; print > d"."c".entry"}if(a==1){print >> d"."c".entry"}}' d=$(date +%Y%m%d) file 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.