Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/kubernetes/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux awk模式可以匹配多行吗?_Linux_Awk - Fatal编程技术网

Linux awk模式可以匹配多行吗?

Linux awk模式可以匹配多行吗?,linux,awk,Linux,Awk,我有一些复杂的日志文件,我需要编写一些工具来处理它们。我一直在玩awk,但我不确定awk是否是适合这个的工具 我的日志文件是OSPF协议解码的打印输出,其中包含各种协议PKT及其内容的文本日志,以及用其值标识的各种协议字段。我想处理这些文件并只打印出特定PKT的特定日志行。每个pkt日志可以由该pkt条目的不同行数组成 awk似乎能够处理与模式匹配的单行。我可以找到所需的pkt,但我需要匹配后面几行中的模式,以确定它是否是我要打印的pkt 另一种方式是,我希望隔离日志文件中的几行,并根据几行上的

我有一些复杂的日志文件,我需要编写一些工具来处理它们。我一直在玩awk,但我不确定awk是否是适合这个的工具

我的日志文件是OSPF协议解码的打印输出,其中包含各种协议PKT及其内容的文本日志,以及用其值标识的各种协议字段。我想处理这些文件并只打印出特定PKT的特定日志行。每个pkt日志可以由该pkt条目的不同行数组成

awk似乎能够处理与模式匹配的单行。我可以找到所需的pkt,但我需要匹配后面几行中的模式,以确定它是否是我要打印的pkt

另一种方式是,我希望隔离日志文件中的几行,并根据几行上的模式匹配打印出特定pkt的详细信息

由于awk似乎是基于行的,我不确定这是否是最好的工具

如果awk能做到这一点,它是如何做到的?如果没有,对使用哪种工具进行此操作有何建议?

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 ""
  }
}