使用 AWK(或 SED)获取字符串之间的文本 - 包括 START 字符串但排除 END 字符串
Use AWK (or SED) to get text between strings - include START string but exclude END string
我正在尝试使用 AWK(或 SED 或两者的组合)来解析包含特定字符串“Info:AgentSession
”的日志文件。
我想包含包含“Info:AgentSession
”的 START 字符串的行,但不包含 END 字符串行,这将是“[2015-
”。
这是 CentOS 服务器上的文本日志文件的片段:
[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 命令有关吗?
你可以使用一个简单的循环 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' ' ~ /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
.
使用awk
:
awk '/^[[]/{f=0} /Info:AgentSession/{f=1} f' file
工作原理
awk
遍历每行输入。对于每一行,程序决定是将变量 f
设置为真 (1) 还是假 (0)。如果 f
为真,则打印该行。
/^[[]/{f=0}
只要一行以 [
开头,f
就会设置为 false。
/Info:AgentSession/{f=1}
如果该行包含字符串 Info:AgentSession
,则先前的命令被覆盖并且 f
设置为 true。
f
如果 f
为真,则 awk
打印该行。
以上是 shorthand for f{print [=24=]}
其中,在 awk 中,[=25=]
表示整行。
这可能适合您 (GNU sed):
sed -n '/Info:AgentSession/,/^$/p' file
我正在尝试使用 AWK(或 SED 或两者的组合)来解析包含特定字符串“Info:AgentSession
”的日志文件。
我想包含包含“Info:AgentSession
”的 START 字符串的行,但不包含 END 字符串行,这将是“[2015-
”。
这是 CentOS 服务器上的文本日志文件的片段:
[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 命令有关吗?
你可以使用一个简单的循环 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' ' ~ /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
.
使用awk
:
awk '/^[[]/{f=0} /Info:AgentSession/{f=1} f' file
工作原理
awk
遍历每行输入。对于每一行,程序决定是将变量 f
设置为真 (1) 还是假 (0)。如果 f
为真,则打印该行。
/^[[]/{f=0}
只要一行以
[
开头,f
就会设置为 false。/Info:AgentSession/{f=1}
如果该行包含字符串
Info:AgentSession
,则先前的命令被覆盖并且f
设置为 true。f
如果
f
为真,则awk
打印该行。以上是 shorthand for
f{print [=24=]}
其中,在 awk 中,[=25=]
表示整行。
这可能适合您 (GNU sed):
sed -n '/Info:AgentSession/,/^$/p' file