按线程解析日志文件部分

rzi*_*r72 1 bash perl awk grep sed

假设有一个像下面这样的示例日志文件,它是由 Java 程序中的多个线程异步写入的。

使用 grep/sed/awk/perl 之类的工具 - 是否有一种简单的方法可以解析仅与 [ServerThread-4] 行相关的所有信息,以及与该线程相关的任何 XML 数据.

但是我不想要任何 [ServerThread-10](或其他线程)行,或者那些不相关线程的这些行之后可能出现的任何 XML 数据。

我尝试像这样使用 sed 和 awk,但这些都不起作用,大概是因为我的开始和结束标记是一样的:

sed -n "/\[ServerThread-4\]/,/\[ServerThread-4\]/p" file.log > file-sed.log
Run Code Online (Sandbox Code Playgroud)
awk "/\[ServerThread-4\]/{flag=1;next}/\[ServerThread-4\]/{flag=0}flag" file.log > file-awk.log
Run Code Online (Sandbox Code Playgroud)

示例文件:

2020-09-22 18:06:24,333 [ServerThread-10] DEBUG com.company.abc.Time - CALCULATE_DATA,ServerThread-10,Request,7,linecount=2
2020-09-22 18:06:24,334 [ServerThread-10] DEBUG com.company.abc.webservice.wsc - Web service transfer time out set to: 130000 (ms)
2020-09-22 18:06:24,563 [ServerThread-4] DEBUG com.company.abc.function - XYZ Function Handler: class com.company.abc.function.XYZCalcDocHandler
2020-09-22 18:06:24,563 [ServerThread-4] DEBUG com.company.abc.function - num row 1
2020-09-22 18:06:24,563 [ServerThread-4] DEBUG com.company.abc.function - TAX_PER_ITEM
2020-09-22 18:06:24,564 [ServerThread-4] DEBUG com.company.abc.function - Request XYZ XML
<SOME_XML><ITEM>THREAD-4-DATA</ITEM></SOME_XML>
2020-09-22 18:06:24,564 [ServerThread-4] DEBUG com.company.abc.function - Using transform: quote.xsl
2020-09-22 18:06:24,569 [ServerThread-4] DEBUG com.company.abc.function - transformXml() = 5 (ms)
2020-09-22 18:06:24,569 [ServerThread-4] DEBUG com.company.abc.function - Request XML
<?xml version="1.0" encoding="UTF-8"?>
<DataEnvelope xmlns="urn:inc:blah:tps:7:0">
<OtherXml>
   <Element>Thread-4-Data</Element>
</OtherXml>
</DataEnvelope>
2020-09-22 18:06:24,569 [ServerThread-4] DEBUG com.company.abc.Time - CALCULATE_DATA,ServerThread-4,Request,6,linecount=1
2020-09-22 18:06:24,569 [ServerThread-4] DEBUG com.company.abc.webservice.wsc - Web service transfer time out set to: 130000 (ms)
2020-09-22 18:06:24,669 [ServerThread-10] DEBUG com.company.abc.Time - CALCULATE_DATA,ServerThread-10,Send,335,linecount=2
2020-09-22 18:06:24,669 [ServerThread-10] INFO  com.company.abc.function - Process response
2020-09-22 18:06:24,670 [ServerThread-10] DEBUG com.company.abc.function - Response XML
<DataEnvelope>
    <Login>Thread-10-User</Login>
</DataEnvelope>
2020-09-22 18:06:24,670 [ServerThread-10] DEBUG com.company.abc.function - Processing response line items
2020-09-22 18:06:24,670 [ServerThread-10] DEBUG com.company.abc.Time - CALCULATE_DATA,ServerThread-10,Response,1,linecount=2
2020-09-22 18:06:24,671 [ServerThread-10] DEBUG com.company.abc.function - Response XYZ XML
<CALCULATE_DATA><CLIENT>100</CLIENT><COMPANY>1000</COMPANY></CALCULATE_DATA>
2020-09-22 18:06:24,671 [ServerThread-10] DEBUG com.company.abc.Time - CALCULATE_DATA,ServerThread-10,Total,345,linecount=2
2020-09-22 18:06:24,923 [ServerThread-4] DEBUG com.company.abc.Time - CALCULATE_DATA,ServerThread-4,Send,354,linecount=1
2020-09-22 18:06:24,923 [ServerThread-4] INFO  com.company.abc.function - Process response
2020-09-22 18:06:24,923 [ServerThread-4] DEBUG com.company.abc.function - Normalizing CDATA elements
2020-09-22 18:06:24,923 [ServerThread-4] DEBUG com.company.abc.function - Response XML
<DataEnvelope>
    <Login>Thread-4-User</Login>
</DataEnvelope>
2020-09-22 18:06:24,923 [ServerThread-4] DEBUG com.company.abc.function - Processing response line items
2020-09-22 18:06:24,924 [ServerThread-4] DEBUG com.company.abc.Time - CALCULATE_DATA,ServerThread-4,Response,1,linecount=1
2020-09-22 18:06:24,924 [ServerThread-4] DEBUG com.company.abc.function - Response XYZ XML
<CALCULATE_DATA><CLIENT>200</CLIENT><COMPANY>2000</COMPANY></CALCULATE_DATA>
2020-09-22 18:06:24,924 [ServerThread-4] DEBUG com.company.abc.Time - CALCULATE_DATA,ServerThread-4,Total,361,linecount=1
Run Code Online (Sandbox Code Playgroud)

zdi*_*dim 5

在这个问题中有些事情我不确定,包括所需输出的形式。

如果您希望所有行以其中的开头和之后的行开始[ServerThread-4],直到任何行[ServerThread-N]whereN 不是 a4,那么您可以使用 Perl 的范围运算符

perl -wne'print if /\[ServerThread-4\]/ .. /\[ServerThread-[^4]+\]/ 
                and not /\[ServerThread-( [^4][0-9]* | 4[0-9]+ )\]/x' file 
Run Code Online (Sandbox Code Playgroud)

这会产生我认为需要的输出,如下所示,但请参阅注释

这种方法做了一些假设,所以请检查它如何满足需要。最重要的是,它假设每个部分ServerThread-N都是完全隔离的,彼此分开(不混合)。

文件是“由多个线程异步写入”的说法有点吓人;这些线程是否组装它们的输出,然后使用一些基于线程的“锁”(或每个打印的锁)写入这些块,或者将这些输出块发送到主线程以良好的顺序写入它们,或者发送以某种方式标记的各个行……?

如果线程只是简单地将行转储到磁盘,那么就不能再可靠地将输出部分与各种线程分开。由于不同的执行线程盲目地访问相同的资源,因此即使是单独的行也可能重叠并被破坏。

上述单行的输出,在提供的文件上

perl -wne'print if /\[ServerThread-4\]/ .. /\[ServerThread-[^4]+\]/ 
                and not /\[ServerThread-( [^4][0-9]* | 4[0-9]+ )\]/x' file 
Run Code Online (Sandbox Code Playgroud)

(我在测试文件中添加了[ServerThread-14]和行...-40


注意两个额外的条件(在正则表达式中的交替),而不是建立范围的条件。第一个,明确排除带有关闭范围运算符的短语的行,是因为

范围运算符保持真直到正确的操作数为真,之后范围运算符变为假

(重点 - 倾斜的块大写字母 - 来自文档)当带有结束标记的行紧跟在开始范围的行之后时,这会咬人,因此对其进行了明确测试。

取而代之的是,我们可以使用范围运算符返回范围中的序列号(如果为 false,则为空字符串),该序列号在最后一行E0附加到它的后面。这正是为了可以检查范围的最后一行(当结束标记评估为真时)。然后我们可以做

perl -wne' print if 
    $r = /\[ServerThread-4\]/ .. /\[ServerThread-([^4][0-9]*|4[0-9]+)\]/ 
    and not $r =~ /E0/
' file
Run Code Online (Sandbox Code Playgroud)

第二个额外条件现在作为交替移动到结束标记的正则表达式中。这是必要的,以排除服务器线程数开始4,然后有更多的数字(像ServerThread-40),还有什么使这是一个有点笨拙。但是如果不需要这个条件(很有可能)那么这会进一步简化,并且 usingE0确实给了我们一个更好的表达。