【问题标题】:Use AWK (or SED) to get text between strings - include START string but exclude END string使用 AWK(或 SED)获取字符串之间的文本 - 包括 START 字符串但不包括 END 字符串
【发布时间】:2015-06-04 01:16:50
【问题描述】:

我正在尝试使用 AWK(或 SED 或两者的组合)来解析包含特定字符串“Info:AgentSession”的日志文件。 我想包含包含 START 字符串“Info:AgentSession”的行,但不包含 END 字符串行,即“[2015-”。

这是 CentOS 服务器上文本日志文件的 sn-p:


[2015-03-30 12:23:10.999] [124] [Info:AgentSession] Handling Agent message for PieraC 
Request: ReceiveReady
Action: DoNotDisturb

[2015-03-30 12:23:11.000] [124] [Info:AgentSession] Sending agent message to PieraC 
Response: ReceiveReady
RequestId: 
Status: Ok
Message: 
IsReady: False

[2015-03-30 12:23:11.000] [49] [Info:Database] (BZ2411) (SqlTaskWorker.ProcessTasks) Attempting to run task. Thread: SqlTaskWorker-37. StartTime: 1/1/0001 12:00:00 AM. ConnectionTimeout: 15. ConnectionState: Open.

[2015-03-30 12:23:11.501] [111] [Info:Dialer] Sending Dialer message
Action: UsmCommand
Command: Transfer
IsTransfered: False

[2015-03-30 12:23:11.502] [111] [Info:AgentSession] Sending agent message to MatthewW 
ActivityState: Wrapup
IsReady: False
IsSipRegistered: True

[2015-03-30 12:23:11.502] [79] [Info:Database] (BZ2411) (SqlTask.Execute) Attempting to start. Thread: SqlTaskWorker-67. 

[2015-03-30 12:23:16.207] [124] [Info:AgentSession] Sending agent message to PieraC 
Response: NonQuery
Status: Ok
Message: Query sent successfully

[2015-03-30 12:23:16.207] [88] [Info:Database] (BZ2411) (SqlTaskWorker.ProcessTasks) Attempting to run task. Thread: SqlTaskWorker-76. 
[2015-03-30 12:23:16.207] [88] [Info:Database] (BZ2411) (SqlTask.Execute) Attempting to start. Thread: SqlTaskWorker-76. 
[2015-03-30 12:23:16.208] [88] [Info:Database] (BZ2411) (SqlNonQueryTask.ExecuteCommand) Attempting to start. Thread: SqlTaskWorker-76. 
[2015-03-30 12:23:16.268] [124] [Info:AgentSession] Handling Agent message for PieraC 
Request: CallAction
CallDisposition: 


当我运行以下命令时:


awk '/Info:AgentSession/ {flag=1;next} /\[2015-/{flag=0} flag {print}' test.log


我得到以下输出:


Request: ReceiveReady
Action: DoNotDisturb

Response: ReceiveReady
RequestId:
Status: Ok
Message:
IsReady: False

ActivityState: Wrapup
IsReady: False
IsSipRegistered: True

Response: NonQuery
Status: Ok
Message: Query sent successfully

Request: CallAction
CallDisposition:


但我希望这个输出包括“Info:AgentSession”的 START 字符串,所以实际上最终看起来像这样(省略不引用 的日志的所有其他部分START 字符串,使用 DATE 字符串“[2015-” 的开头作为 END 字符串):


[2015-03-30 12:23:10.999] [124] [Info:AgentSession] Handling Agent message for PieraC 
Request: ReceiveReady
Action: DoNotDisturb

[2015-03-30 12:23:11.000] [124] [Info:AgentSession] Sending agent message to PieraC 
Response: ReceiveReady
RequestId: 
Status: Ok
Message: 
IsReady: False

[2015-03-30 12:23:11.502] [111] [Info:AgentSession] Sending agent message to MatthewW 
ActivityState: Wrapup
IsReady: False
IsSipRegistered: True


[2015-03-30 12:23:16.207] [124] [Info:AgentSession] Sending agent message to PieraC 
Response: NonQuery
Status: Ok
Message: Query sent successfully

[2015-03-30 12:23:16.268] [124] [Info:AgentSession] Handling Agent message for PieraC 
Request: CallAction
CallDisposition: 


这可能与简单的 AWK 或 SED 命令有关吗?

【问题讨论】:

  • print 命令添加到第一个块。

标签: parsing awk sed between


【解决方案1】:

使用awk

awk '/^[[]/{f=0} /Info:AgentSession/{f=1} f' file

工作原理

awk 循环遍历每一行输入。对于每一行,程序决定是否将变量 f 设置为 true (1) 或 false (0)。如果f 为真,则打印该行。

  • /^[[]/{f=0}

    只要一行以[ 开头,f 就会设置为 false。

  • /Info:AgentSession/{f=1}

    如果该行包含字符串Info:AgentSession,则前面的命令将被覆盖并将f 设置为true。

  • f

    如果f 为真,则awk 打印该行。

    以上是f{print $0} 的简写,在awk 中,$0 表示整行。

【讨论】:

  • 完美! - 感谢您的解决方案 + 解释@John1024
【解决方案2】:

您可以使用sed 的简单循环:

sed -n '/Info:AgentSession/{:a;p;n;/^$/!ba;p}' input.file

该命令搜索包含模式/Info:AgentSession/ 的行。如果出现这样的行,花括号{} 之间的以下块将被执行。在该块中,我们为循环定义了一个开始标签,简称为:a。然后我们打印当前行p,从输入n获取下一行,并检查它是否为空/^$/。如果行不为空!,我们将退回到循环的开始ba。否则,我们打印该空行作为记录分隔符,并在下一行输入中重新开始搜索/Info:AgentSession/

使用-n 命令行选项抑制其他行的输出。

输出:

[2015-03-30 12:23:10.999] [124] [Info:AgentSession] Handling Agent message for PieraC 
Request: ReceiveReady
Action: DoNotDisturb
[2015-03-30 12:23:11.000] [124] [Info:AgentSession] Sending agent message to PieraC 
Response: ReceiveReady
RequestId: 
Status: Ok
Message: 
IsReady: False

[2015-03-30 12:23:11.502] [111] [Info:AgentSession] Sending agent message to MatthewW 
ActivityState: Wrapup
IsReady: False
IsSipRegistered: True

[2015-03-30 12:23:16.207] [124] [Info:AgentSession] Sending agent message to PieraC 
Response: NonQuery
Status: Ok
Message: Query sent successfully

[2015-03-30 12:23:16.268] [124] [Info:AgentSession] Handling Agent message for PieraC 
Request: CallAction
CallDisposition: 

另一种方法是像这样使用awk

awk -F'\n' '$1 ~ /Info:AgentSession/' RS='\n\n' ORS='\n\n' input.file

我将输入和输出分隔符定义为两个换行符的序列。字段分隔符是一个换行符。如果我们记录的第一个字段包含模式Info:AgentSession,我们将打印整条记录。


顺便说一句,上面的sed 命令也可以在没有-n 选项的情况下编写:

sed '/Info:AgentSession/{:a;n;/^$/!ba;p};d' input.file

在这种情况下,我们正在搜索包含/Info:AgentSession/ 的行,如果找到这样的行,则在大括号之间执行以下块。我们定义一个标签:a,打印当前行并从输入n获取下一行。只要/^$/! 后面有非空行,我们就会退回到循环的开头ba,否则我们会将该空行打印为记录分隔符p。所有其他行都被删除d

【讨论】:

  • 感谢@hek2mgl。我试过这个,但我只得到第一行的输出,而不是表达式之间需要的所有行。例如,我只得到如下一行:[2015-03-30 12:23:16.207] [124] [Info:AgentSession] Sending agent message to PieraC [2015-03-30 12:23:16.268] [124] [Info:AgentSession] Handling Agent message for PieraC 每行下方没有任何部分。
  • 是的,有一个小错误。 (我用n 替换了N)。它现在应该可以工作了。
  • 是的!这现在也适用于我,再次感谢 hek2mgl!
  • @ChrisCharles 还要检查我添加的awk 替代方案。 awk 处理更直观,因为它将块简单地定义为记录。
【解决方案3】:

这可能对你有用(GNU sed):

sed -n '/Info:AgentSession/,/^$/p' file

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-10
    • 2018-11-26
    • 2020-11-13
    • 2016-03-24
    • 2021-11-24
    • 1970-01-01
    • 2020-10-22
    相关资源
    最近更新 更多