使用 grep/sed 提取第一个模式,然后提取在第一个模式之前出现并与第一个模式相关的第二个模式

使用 grep/sed 提取第一个模式,然后提取在第一个模式之前出现并与第一个模式相关的第二个模式

我试图.htm在模式发生时从文件中提取特定行(在下面的示例中为“事件 100”),但同时我还需要检索另一个模式,该模式与第一个模式相关,但来自以下之一它上面的线。第二个模式代表第一个模式发生的时间:

例子:

<AZ>207994</AZ>
<AZ>09:10:41.9</AZ>
<AZ>02/04</AZ>
<AZ>[990875]</AZ>
<TR VALIGN=TOP>
<AZ>207995</AZ>
<AZ>09:10:56.4</AZ>
<AZ>02/04</AZ>
<AZ>[990876]</AZ>
<AZ>30718</AZ><AZ><!--void--></AZ><AZ><!--void--></AZ><AZ><!--void--></AZ>
<AZ>TN (speed)  Event 3 occurred</TD></TR>
<TR VALIGN=TOP>
<AZ>30719</TD><TD><!--void--></AZ><AZ><!--void--></AZ><AZ><!--void--></AZ>
<AZ>TN (speed)  Event 100 occurred</TD></TR>
<TR VALIGN=TOP>
<AZ>30720</AZ><AZ><!--void--></AZ><AZ><!--void--></AZ><AZ><!--void--></AZ>

我想要以下结果:

02/04 09:10:56.4 [990876] 发生事件 100

答案1

我想出了这个令人讨厌的单行代码(为了可读性而换行):

awk -F'[<>]'  '($0 ~ /[0-9][0-9]:[0-9][0-9]:[0-9][0-9]/) {time=$3}
               ($0 ~ /[0-9][0-9]\/[0-9][0-9]/) {date=$3}
               ($0 ~ /\[[0-9]+\]/) {tag=$3}
               ($0 ~ /Event 100 occurred/) { print date, time, tag, "Event 100 occurred"}' < testfile

这会一致地收集类似时间、日期或标签 ([12345]) 的内容,如果出现类似“发生事件 100”的行,则会打印变量的当前内容。这是想要的输出吗?

答案2

这应该可以解决问题:

(grep -oP "Event 100" file && \
sed -ne 's/<\/\?AZ>//g' -e '7,9p' file) | \
awk 'BEGIN {RS=""; FS="\n";} \
{printf "%s %s %s %s\n", $3, $2, $4, $1}'

解释:

  • file:包含上面输出的文件
  • grep -oP "Event 100" file:搜索“事件 100”
  • sed -ne 's/<\/\?AZ>//g' -e '7,9p' file:如果找到该字符串,则删除<AZ></AZ>标签,并打印第 7 至 9 行
  • awk 'BEGIN {RS=""; FS="\n";}:将awk的字段分隔符设置为换行符
  • {printf "%s %s %s %s\n", $3, $2, $4, $1}:并按所需顺序打印输出

输出(如果找到字符串):

02/04 09:10:56.4 [990876] Event 100

如果未找到字符串,则没有输出。

相关内容