Parsing 使用AWK(或SED)获取字符串之间的文本-包括开始字符串但不包括结束字符串

Parsing 使用AWK(或SED)获取字符串之间的文本-包括开始字符串但不包括结束字符串,parsing,awk,sed,between,Parsing,Awk,Sed,Between,我试图使用AWK(或SED或两者的组合)解析出包含特定字符串“Info:AgentSession”的日志文件。 我想包括包含“Info:AgentSession”字符串的开始行,但不包括结束字符串行,即“[2015-” 以下是CentOS服务器上的文本日志文件片段: 当我运行以下命令时: 我得到以下输出: 但是我希望这个输出包括“Info:AgentSession”的START字符串,因此实际上最终看起来是这样的(使用[2015-字符串的开头,省略日志中不引用START字符串的所有其

我试图使用AWK(或SED或两者的组合)解析出包含特定字符串“
Info:AgentSession
”的日志文件。 我想包括包含“
Info:AgentSession
”字符串的开始行,但不包括结束字符串行,即“
[2015-

以下是CentOS服务器上的文本日志文件片段:



当我运行以下命令时:



我得到以下输出:



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



用一个简单的AWK或SED命令可以做到这一点吗?

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

sed -n '/Info:AgentSession/{:a;p;n;/^$/!ba;p}' input.file
该命令搜索包含模式
/Info:AgentSession/
的行。如果出现这样的行,则在大括号
{}之间显示以下块
get被执行。在该块中,我们为循环定义一个开始标签,简单地调用它
:a
。然后我们打印当前行
p
,从输入
n
中获取下一行,并检查它是否为空
/^$/
。如果行不是空的
我们返回到循环的开始
ba
。否则我们打印将该空行用作记录分隔符,然后在下一行输入中再次开始搜索
/Info:AgentSession/

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

输出:

[2015-03-30 12:23:10.999][124][Info:AgentSession]处理PieraC的代理消息
请求:破产管理人
行动:不要打扰
[2015-03-30 12:23:11.000][124][Info:AgentSession]向PieraC发送代理消息
答复:破产管理署
请求ID:
状态:Ok
信息:
伊斯雷迪:错
[2015-03-30 12:23:11.502][111][Info:AgentSession]向MatthewW发送代理消息
活动状态:Wrapup
伊斯雷迪:错
这是真的
[2015-03-30 12:23:16.207][124][Info:AgentSession]向PieraC发送代理消息
答复:非查询
状态:Ok
消息:查询已成功发送
[2015-03-30 12:23:16.268][124][Info:AgentSession]PieraC处理代理信息
请求: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
中获取下一行。只要在
/^$/!
后面有非空行,我们就后退一步到循环的开始处,否则我们将该空行打印为记录分隔符
p
。使用
awk
删除所有其他行
d

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
    打印该行

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

这可能适合您(GNU-sed):


在第一个块中添加一个
print
命令。谢谢@hek2mgl。我尝试了这一点,但我只得到了第一行的输出,而没有得到表达式之间所需的所有行。因此,例如,我只得到一行,看起来像:
[2015-03-30 12:23:16.207][124][Info:AgentSession Info]向PieraC发送代理消息[2015-03-30 12:23:16.268][124][Info:AgentSession]处理PieraC的代理消息
,每行下面没有任何部分。是的,出现了一个小错误。(我将
N
替换为
N
)。它现在应该可以工作了。是的!这对我来说也很有效,再次感谢hek2mgl!@ChrisCharles还检查了我添加的
awk
替代方案。它更直观
awk
处理,因为它将块简单地定义为记录。太好了!-感谢解决方案+解释@John1024
sed -n '/Info:AgentSession/{:a;p;n;/^$/!ba;p}' input.file
awk -F'\n' '$1 ~ /Info:AgentSession/' RS='\n\n' ORS='\n\n' input.file
sed '/Info:AgentSession/{:a;n;/^$/!ba;p};d' input.file
awk '/^[[]/{f=0} /Info:AgentSession/{f=1} f' file
sed -n '/Info:AgentSession/,/^$/p' file