因此,当我处理正在处理的特定日志集时,先打开一个文件,cat
然后使用它来获取匹配的行只能让我到目前为止。grep
它需要一种将行与模式匹配的方法,但仅返回匹配后的行部分。比赛前后的部分会不断变化。我已经使用了sed
or 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
第一个命令,尽管这不是标准/可移植的。s
s//\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 正则表达式引擎“字面理解”。
其他细微差别包括:
- Raku 将捕获编号更改为从 $0 开始(Perl 从 $1 开始),
- 在 Raku 中,前导
~
波形符用于对匹配对象进行字符串化,并且 - 在 Perl 中,
-E
必须使用命令行标志来启用该say
功能。
http://www.wall.org/~larry/natural.html
https://www.perl.org/
https://www.raku.org/