Linux awk模式可以匹配多行吗?
我有一些复杂的日志文件,我需要编写一些工具来处理它们。我一直在玩awk,但我不确定awk是否是适合这个的工具 我的日志文件是OSPF协议解码的打印输出,其中包含各种协议PKT及其内容的文本日志,以及用其值标识的各种协议字段。我想处理这些文件并只打印出特定PKT的特定日志行。每个pkt日志可以由该pkt条目的不同行数组成 awk似乎能够处理与模式匹配的单行。我可以找到所需的pkt,但我需要匹配后面几行中的模式,以确定它是否是我要打印的pkt 另一种方式是,我希望隔离日志文件中的几行,并根据几行上的模式匹配打印出特定pkt的详细信息 由于awk似乎是基于行的,我不确定这是否是最好的工具 如果awk能做到这一点,它是如何做到的?如果没有,对使用哪种工具进行此操作有何建议?Linux awk模式可以匹配多行吗?,linux,awk,Linux,Awk,我有一些复杂的日志文件,我需要编写一些工具来处理它们。我一直在玩awk,但我不确定awk是否是适合这个的工具 我的日志文件是OSPF协议解码的打印输出,其中包含各种协议PKT及其内容的文本日志,以及用其值标识的各种协议字段。我想处理这些文件并只打印出特定PKT的特定日志行。每个pkt日志可以由该pkt条目的不同行数组成 awk似乎能够处理与模式匹配的单行。我可以找到所需的pkt,但我需要匹配后面几行中的模式,以确定它是否是我要打印的pkt 另一种方式是,我希望隔离日志文件中的几行,并根据几行上的
awk'/pattern start/,/pattern end/
Awk可以很容易地检测到模式的多行组合,但您需要在代码中创建一个称为a的元素来识别序列 考虑以下输入:
how
second half #1
now
first half
second half #2
brown
second half #3
cow
正如您所看到的,很容易识别单一模式。现在,我们可以编写一个awk程序,它只在后半部分前面有前半行时才识别后半部分。(使用更复杂的状态机,您可以检测任意序列的模式。)
如果运行此选项,您将看到:
second half #2
现在,这个例子非常简单,仅仅是一个状态机。感兴趣的状态仅在if语句的持续时间内持续,而前面的状态是隐式的,具体取决于lastLine的值。在更规范的状态机中,您将保留一个显式状态变量,并根据现有状态和当前输入从一个状态转换到另一个状态。但你可能不需要那么多的控制机制
`pcregrep -M` works pretty well for this.
来自pcregrep(1):
-M、 --多行
允许模式匹配多行。当给出此选项时,
模式可能有用地包含文字换行符和内部字符
^和$字符的出现。成功匹配的输出
可由超过
一行,最后一行是比赛结束的那一行。如果
匹配的字符串以换行符序列结束,输出在
那条线的尽头
设置此选项后,将在“多行”中调用PCRE库
模式可以匹配的行数是有限制的,
通过pcregrep在扫描时缓冲输入文件的方式强制执行
信息技术但是,pcregrep确保至少包含8K个字符或其他字符
文件的副本(以较短者为准)可供转发
与之前的8K字符(或所有
以前的字符(如果少于8K)保证可用
用于查找后面的断言。输入为空时,此选项不起作用
逐行读取(请参阅--line buffered.)
我经常用sendmail日志做这种事情 鉴于:
Jan 15 22:34:39 mail sm-mta[36383]: r0B8xkuT048547: to=<www@web3>, delay=4+18:34:53, xdelay=00:00:00, mailer=esmtp, pri=21092363, relay=web3., dsn=4.0.0, stat=Deferred: Operation timed out with web3.
Jan 15 22:34:39 mail sm-mta[36383]: r0B8hpoV047895: to=<www@web3>, delay=4+18:49:22, xdelay=00:00:00, mailer=esmtp, pri=21092556, relay=web3., dsn=4.0.0, stat=Deferred: Operation timed out with web3.
Jan 15 22:34:51 mail sm-mta[36719]: r0G3Youh036719: from=<obfTaIX3@nickhearn.com>, size=0, class=0, nrcpts=0, proto=ESMTP, daemon=IPv4, relay=[50.71.152.178]
Jan 15 22:35:04 mail sm-mta[36722]: r0G3Z2SF036722: lost input channel from [190.107.98.82] to IPv4 after rcpt
Jan 15 22:35:04 mail sm-mta[36722]: r0G3Z2SF036722: from=<amahrroc@europe.com>, size=0, class=0, nrcpts=0, proto=SMTP, daemon=IPv4, relay=[190.107.98.82]
Jan 15 22:35:36 mail sm-mta[36728]: r0G3ZXiX036728: lost input channel from ABTS-TN-dynamic-237.104.174.122.airtelbroadband.in [122.174.104.237] (may be forged) to IPv4 after rcpt
Jan 15 22:35:36 mail sm-mta[36728]: r0G3ZXiX036728: from=<clunch.hilarymas@javagame.ru>, size=0, class=0, nrcpts=0, proto=SMTP, daemon=IPv4, relay=ABTS-TN-dynamic-237.104.174.122.airtelbroadband.in [122.174.104.237] (may be forged)
要获得以下输出:
$ mqsearch airtel /var/log/maillog
Jan 15 22:35:36 mail sm-mta[36728]: r0G3ZXiX036728: lost input channel from ABTS-TN-dynamic-237.104.174.122.airtelbroadband.in [122.174.104.237] (may be forged) to IPv4 after rcpt
Jan 15 22:35:36 mail sm-mta[36728]: r0G3ZXiX036728: from=<clunch.hilarymas@javagame.ru>, size=0, class=0, nrcpts=0, proto=SMTP, daemon=IPv4, relay=ABTS-TN-dynamic-237.104.174.122.airtelbroadband.in [122.174.104.237] (may be forged)
$mqsearch airtel/var/log/maillog
1月15日22:35:36邮件sm mta[36728]:r0G3ZXiX036728:rcpt后从ABTS-TN-dynamic-237.104.174.122.airtelbroadband.in[122.174.104.237](可能伪造)到IPv4的输入通道丢失
一月十五日22:35:36邮件sm mta[36728]:r0G3ZXiX036728:from=,size=0,class=0,nrcpts=0,proto=SMTP,daemon=IPv4,relay=ABTS-TN-dynamic-237.104.174.122.airtelbroadband.in[122.174.104.237](可能是伪造的)
这里的想法是,我正在打印与要搜索的字符串的Sendmail队列ID匹配的所有行。代码的结构当然是日志文件结构的产物,因此您需要为您试图分析和提取的数据定制解决方案。Awk实际上是基于记录的。默认情况下,它将一行视为一条记录,但您可以使用RS(记录分隔符)变量对其进行更改 实现这一点的一种方法是使用sed进行第一次传递(如果愿意的话,您也可以使用awk进行此操作),以不同的字符(如表单提要)分隔记录。然后,您可以编写awk脚本,将行组视为单个记录 例如,如果这是您的数据:
animal 0
name: joe
type: dog
animal 1
name: bill
type: cat
animal 2
name: ed
type: cat
要使用表单提要分隔记录,请执行以下操作:
$ cat data | sed $'s|^\(animal.*\)|\f\\1|'
现在我们将把它通过awk。以下是有条件打印记录的示例:
$ cat data | sed $'s|^\(animal.*\)|\f\\1|' | awk '
BEGIN { RS="\f" }
/type: cat/ { print }'
产出:
animal 1
name: bill
type: cat
animal 2
name: ed
type: cat
编辑:作为奖励,下面介绍如何使用awk ward ruby(-014表示使用表单提要(八进制代码014)作为记录分隔符):
awk能够从开始模式处理到结束模式
/start-pattern/,/end-pattern/ {
print
}
我在寻找如何匹配
* Implements hook_entity_info_alter().
*/
function file_test_entity_type_alter(&$entity_types) {
如此创造
/\* Implements hook_/,/function / {
print
}
这是我需要的内容。一个更复杂的示例是跳过行并删除非空间部分。注awk是一种记录(行)和字(按空格分割)工具
希望这也有帮助
另请参见您能举一些log entires.awk的例子吗?它是面向记录的,而不是面向行的,因此几乎可以肯定它是适合这项工作的工具。如果您发布一些示例输入和所需输出,我们可以向您展示如何在awk中实现这一点。感谢各位的回答——他们都很有帮助。在您给出的示例中,我相信您可以设置
RS=“animal”
。是的,这也可以,或者在这个特定示例中设置“\n\n”。我宁愿让RS实际分离完整的记录,也不要使用任何记录。取决于数据格式。这里我想展示一些完全定制的东西,因为这可以用于日志解析。
/start-pattern/,/end-pattern/ {
print
}
* Implements hook_entity_info_alter().
*/
function file_test_entity_type_alter(&$entity_types) {
/\* Implements hook_/,/function / {
print
}
# start,end pattern match using comma
/ \* Implements hook_(.*?)\./,/function (.\S*?)/ {
# skip PHP multi line comment end
$0 ~ / \*\// skip
# Only print 3rd word
if ($0 ~ /Implements/) {
hook=$3
# scrub of opening parenthesis and following.
sub(/\(.*$/, "", hook)
print hook
}
# Only print function name without parenthesis
if ($0 ~ /function/) {
name=$2
# scrub of opening parenthesis and following.
sub(/\(.*$/, "", name)
print name
print ""
}
}