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

MaQ*_*eod 161 grep sed text-processing

因此,当我使用我正在处理的特定日志集时,拉开一个文件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 }
Run Code Online (Sandbox Code Playgroud)

我需要的部分是“停滞”后的一切。

这背后的背景是我可以找出某些东西停顿的频率:

cat messages | grep stalled | wc -l
Run Code Online (Sandbox Code Playgroud)

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

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

Gil*_*il' 204

对此的规范工具是sed.

sed -n -e 's/^.*stalled: //p'
Run Code Online (Sandbox Code Playgroud)

详细解释:

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

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

sed -n -e 's/^.*\(stalled: \)/\1/p'
Run Code Online (Sandbox Code Playgroud)

有时您会希望在比赛结束后删除该行的一部分。您可以通过.*$在模式末尾包含它(任何文本.*后跟行尾$)来将其包含在匹配中。除非您将该部分放在替换文本中引用的组中,否则该行的结尾将不会出现在输出中。

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

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

  • @MaQleod 哦,它正在等待标准输入的输入,这是终端,因为您没有重定向它。在这里,您将执行输入重定向 `sed ... &lt;messages`,因为您想要处理来自文件的数据。要处理由另一个命令生成的数据,您可以使用管道:`somecommand | sed ...`。 (2认同)
  • 对,一天结束时那里停电。命令完美运行,谢谢。 (2认同)

Ann*_*sum 112

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

例如:

grep -o 'stalled.*'
Run Code Online (Sandbox Code Playgroud)

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

sed -n -e 's/^.*\(stalled: \)/\1/p'
Run Code Online (Sandbox Code Playgroud)

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

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

grep -o 'stalled.*' | cut -f2- -d:
Run Code Online (Sandbox Code Playgroud)

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

  • 感谢您提到 `-o` 选项!我想指出的是 `grep` 不能将 `\n` 识别为换行符,所以你的第一个例子只匹配第一个 `n` 字符。例如,`echo "Hello Anne" | grep -o 'A[^\n]*'` 返回字符串 `A`。但是,`echo "Hello Anne" | grep -o 'A.*'` 返回预期的 `Anne`,因为 `.` 匹配除换行符以外的任何字符。 (3认同)
  • 请注意,@poige 删除了 `cut` 分隔符 `-d':'` 周围的引号。我发现用引号更容易记住,例如用`-d' '` 或`-d';'`。 (2认同)

小智 5

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

awk -F"stalled" '/stalled/{print $2}' messages
Run Code Online (Sandbox Code Playgroud)

详细解释:

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