仅返回匹配模式之后的行部分

仅返回匹配模式之后的行部分

因此,当我处理正在处理的特定日志集时,先打开一个文件,cat然后使用它来获取匹配的行只能让我到目前为止。grep它需要一种将行与模式匹配的方法,但仅返回匹配后的行部分。比赛前后的部分会不断变化。我已经使用了sedor awk,但无法弄清楚如何过滤该行以删除比赛前的部分,或者仅在比赛后返回部分,这两种方法都可以。这是我需要过滤的行的示例:

2011-11-07T05:37:43-08:00 <0.4> isi-udb5-ash4-1(id1) /boot/kernel.amd64/kernel: [gmp_info.c:1758](pid 40370="kt: gmp-drive-updat")(tid=100872) new group: <15,1773>: { 1:0-25,27-34,37-38, 2:0-33,35-36, 3:0-35, 4:0-9,11-14,16-32,34-38, 5:0-35, 6:0-15,17-36, 7:0-16,18-36, 8:0-14,16-32,34-36, 9:0-10,12-36, 10-11:0-35, 12:0-5,7-30,32-35, 13-19:0-35, 20:0,2-35, down: 8:15, soft_failed: 1:27, 8:15, stalled: 12:6,31, 20:1 }

我需要的部分是“停滞”之后的所有内容。

这背后的背景是我可以找出某些事情停滞的频率:

cat messages | grep stalled | wc -l

我需要做的是找出某个节点已停止了多少次(由“停止”后每个冒号之前的部分表示。如果我只是 grep )(即 20:),它可能会返回出现软失败的行,但是没有停顿,这对我没有帮助,我只需要过滤停顿的部分,这样我就可以从那些停顿的节点中查找特定的节点。

出于所有意图和目的,这是一个带有标准 GNU 核心实用程序的 freebsd 系统,但我无法安装任何额外的东西来提供帮助。

答案1

典型的工具是sed.

sed -n -e 's/^.*stalled: //p'

详细解释:

  • -n意味着默认情况下不打印任何内容。
  • -e后面跟着一个 sed 命令。
  • s是模式替换命令。
  • 正则表达式^.*stalled:与您要查找的模式相匹配,加上任何前面的文本(.*表示任何文本,带有首字母^表示匹配从行的开头开始)。请注意,如果stalled:该行出现多次,则这将与最后一次出现的匹配。
  • 匹配项,即行中直到 的所有内容stalled:,都被空字符串替换(即删除)。
  • 最后的p方法是打印转换后的行。

如果要保留匹配部分,请使用反向引用:在替换部分中指定模式中\1组内的内容。\(…\)这里,你可以stalled:在替换部分再写一次;当您要查找的模式比简单字符串更通用时,此功能非常有用。

sed -n -e 's/^.*\(stalled: \)/\1/p'

有时,您可能想删除匹配后的行部分。您可以通过.*$在模式末尾添加(.*行尾后的任何文本$)将其包含在匹配中。除非您将该部分放在替换文本中引用的组中,否则行尾不会出现在输出中。

作为组和反向引用的进一步说明,该命令交换匹配之前的部分和匹配之后的部分。

sed -n -e 's/^\(.*\)\(stalled: \)\(.*\)$/\3\2\1/p'

获得零件后第一的字符串的出现而不是最后一次(对于字符串可以出现多次的那些行),一个常见的技巧是用换行符(这是不会出现在一行中的一个字符)替换该字符串一次,并且然后删除该换行符之前的所有内容:

sed -n '
  /stalled: / {
    s//\
/
    s/.*\n//p
  }'

在某些实现中,可以编写sed第一个命令,尽管这不是标准/可移植的。ss//\n/

答案2

您已经使用的其他规范工具grep::

例如:

grep -o 'stalled.*'

与 Gilles 的第二个选项结果相同:

sed -n -e 's/^.*\(stalled: \)/\1/p'

-o标志返回--only-matching表达式的一部分,因此不是整行,当然,通常由 grep 完成。

要从输出中删除“stalled :”,我们可以使用第三种规范工具,cut:

grep -o 'stalled.*' | cut -f2- -d:

cut命令使用分隔符:并打印字段 2 直到最后。当然,这是一个偏好问题,但cut我发现语法很容易记住。

答案3

您考虑的另一个规范工具awk可以与以下行一起使用:

awk -F"stalled" '/stalled/{print $2}' messages

详细解释:

  • -F定义该行的分隔符,即“停滞”。分隔符之前的所有内容都用 来寻址$1,分隔符之后的所有内容都用 来寻址$2
  • /reg-ex/搜索匹配的正则表达式,在本例中为“已停止”。
  • {print $<n>}- 打印n列。由于您的分隔符被定义为停止,因此停止后的所有内容都被视为第二列。

答案4

使用 Perl(即 Perl5)和 Raku(以前称为 Perl6):

珀尔:

perl -pe 's/^.*stalled: //; #leaves non-matching and/or blank lines intact

或者:

perl -nE '/^.*stalled: (.*)/ and say $1;'  #removes non-matching lines

乐:

raku -pe 's/^.*stalled\:\s//;' #leaves non-matching and/or blank lines intact

或者:

raku -ne '/^.*stalled\:\s (.*)/ and say ~$0;' #removes non-matching lines

输出(对于上面的第二个 Perl 和第二个 Raku 示例):

12:6,31, 20:1 }

上面的代码在两种语言之间实际上是相同的。最显着的区别是,在 Raku 中,所有非数字/非下划线字符必须转义才能被 Raku 正则表达式引擎“字面理解”。

其他细微差别包括:

  1. Raku 将捕获编号更改为从 $0 开始(Perl 从 $1 开始),
  2. 在 Raku 中,前导~波形符用于对匹配对象进行字符串化,并且
  3. 在 Perl 中,-E必须使用命令行标志来启用该say功能。

http://www.wall.org/~larry/natural.html
https://www.perl.org/
https://www.raku.org/

相关内容