我有一个大致如下所示的日志文件:
Sep 23 10:28:26 node kernel: em0: device is going DOWN
Sep 23 10:28:26 node kernel: em0: device is going UP
Sep 23 10:29:14 node cdsmon: /tmp/instance0 ; core dumped
Sep 23 10:29:14 node cdsmon: /tmp/instance0 ; core dumped
Sep 23 10:28:26 node kernel: em0: device is going DOWN
Sep 23 10:29:14 node cdsmon: /tmp/instance1 ; core dumped
Sep 23 10:28:26 node kernel: em0: device is going UP
Sep 23 10:29:14 node cdsmon: /tmp/instance2 ; core dumped
我想用 检测线条,cdsmon
然后将线条分割;
(以获取/tmp/instance0
和 之类的事件core dumped
)。
为此,我用作sed
:
sed -u -n -e "s/^.*cdsmon: //p" /tmp/dev.log
输出为:
/tmp/instance0 ; core dumped
/tmp/instance0 ; core dumped
/tmp/instance1 ; core dumped
/tmp/instance2 ; core dumped
但是在将这个输出传送到awk
如下所示时,它会给出与上面相同的输出:
sed -u -n -e "s/^.*cdsmon: //p" /tmp/dev.log | awk -F ";" "{print $1}"
尽管-u
从sed
.
谁能指出我是否遗漏了什么?我正在使用带有常规 awk/sed 的 FreeBSD 机器,不幸的是无法安装任何新软件包。
的行为的原因
awk
是您已将程序括在双引号中,这使字符串对 shell 的变量扩展开放。这意味着您运行程序的 shell 将首先展开$1
,并且由于这可能是未定义的,它会展开为空字符串。所以,你的程序相当于
这就是打印整行的原因。这是您应该始终将
awk
(andsed
) 程序包含在单引号中的原因之一。请注意,在大多数情况下,您不需要将输出从管道输入,
sed
反之亦然awk
。在您的示例中,如果您想获取“事件标签”之后的第一个字段,您可以执行以下操作:这将围绕字符串定义一个捕获组
cdsmon:
,直到 first;
,并将整行替换为该捕获组的内容。如果要打印由 记录的事件的摘要
cdsmon
,可以将上述sed
方法扩展为:或者,这是另一种
awk
-only 方法:对于您的示例,两者都将打印
但请注意,该
awk
方法可能会遇到极端情况。它采用模式cdsmon:
和;
作为字段分隔符。当有三个字段时(在您的示例中,它只能发生在cdsmon:
条目中),它会打印第二个和第三个字段,对应于实例名称之后cdsmon:
和原因之后;
。根据手册:
因此,在您的情况下,您可以转义美元符号
$
:但是使用单引号更容易:
您也可以在分隔符之间留出空格,
' ; '
这样您就不会在每行之后以不可见的空格结尾。您也可以只使用
awk
:我会使用
awk
整个操作。在这里,我在冒号上进行拆分,因此在考虑了日期/时间之后,必须将主机匹配应用于第三个字段(14 node cdsmon
例如):这是评论中建议的替代且更简单的解决方案,我们在冒号或分号上拆分,因此必要的字段已经直接在
awk
变量中:你没有说你想如何提取实例和原因(或者如果你做了,我错过了),所以我只是将它们打印在一个字符串中,证明它们已被正确提取。
输出