grep - 显示匹配行的两个部分

3

我已经阅读了grep命令的手册并尝试了一些方法,但是它们都没有起作用,至少对我来说不行。

我想在查看日志时提取一行良好可读的信息。 这是我想要美化的通用日志文件中的一行:

26 Jan 2018 08:32:29,309 [TEXT] (myService-0) long.text.I.dont.care.about.but.is.different.in.every.line: [OTHERTEXT] Text im actually interested in

What I want is this:

26 Jan 2018 08:32:29,309 [TEXT] [OTHERTEXT] Text im actually interested in

我知道使用grep -o -e ".*\[TEXT\]"可以得到第一部分,使用grep -o -e "\[OTHERTEXT\].*"可以得到第二部分。
但是这两个部分不会在同一行显示,即使我将它们组合成grep -o -e ".*\[TEXT\]" -e "\[OTHERTEXT\].*"也不行。 [TEXT][OTHERTEXT]总是存在的,它们是我的“分隔符”,因此可以用来支持提取我需要的部分。
我最初认为可以使用grep -o -e "(.*\[TEXT\]).*(\[OTHERTEXT\].*)",然后以某种方式使用匹配组$1$2,但是要么我看不到方法,要么就没有办法这样做。
有没有办法实现我想要的效果?
首选是使用grep(仅因为我想更多地了解它),但如果不可能,则awksed也可以,只要能够与tail -f一起使用即可。
我也开放其他方法来达到这个目标,所以让我知道有哪些方法可以到达那里。
谢谢,Tobias
5个回答

4
您可以使用 sed 命令:
sed -E 's/(\[TEXT]).*(\[OTHERTEXT])/\1 \2/' file.log

26 Jan 2018 08:32:29,309 [TEXT] [OTHERTEXT] Text im actually interested in

这个sed命令匹配[TEXT][OTHERTEXT]之间的模式,并将它们捕获在两个组中。在替换中,它使用反向引用\1 \2放回这些标记。

1
太好了,谢谢!我只需要做一些小改动:sed -E "s/(.*\[TEXT\]).*(\[OTHERTEXT\].*)/\1 \2/" - ximarin
匹配前后测试使用 .* 并不是必须的。只需要 sed -E 's/(\[TEXT]).*(\[OTHERTEXT])/\1 \2/' 也可以正常工作。 - anubhava
根据James Brown的回答,这是一个针对特定用例更短的sed命令:sed -E "s/\].*\[//" - ximarin
实际上,sed -E "s/\].*\[//" 可能适用于这行代码,但如果在 [TEXT] 之前或之后有另一个 [...],那么它将失败。 - anubhava

1
使用awk,您可以将][之间的所有内容替换为] [
$ awk 'sub(/\].*\[/,"] [")' file
26 Jan 2018 08:32:29,309 [TEXT] [OTHERTEXT] Text im actually interested in

0

将你的 grep 管道传输到

<your grep> | sed "s/(myService-0).*[OTHERTEXT]/(myService-0)[OTHERTEXT]/"

"[OTHERTEXT]" 被称为括号表达式,它可以逐个匹配方括号内的每个字符。 - anubhava

0

你可以用perl来实现这个功能。

$ # note that this will print empty lines when no match is found
$ perl -lne 'print /(.*\[TEXT\] ).*(\[OTHERTEXT\].*)/' ip.txt
26 Jan 2018 08:32:29,309 [TEXT] [OTHERTEXT] Text im actually interested in
$ # you can avoid empty lines by checking for match first
$ perl -lne '/(.*\[TEXT\] ).*(\[OTHERTEXT\].*)/ && print $1,$2' ip.txt
26 Jan 2018 08:32:29,309 [TEXT] [OTHERTEXT] Text im actually interested in

由于您正在处理 tail -f 输出,您可能需要缓冲控制,请参见 如何“grep”连续流? 作为示例


0

你可能需要使用sed来完成你想要的操作:

sed -E 's/(.*\[TEXT]).*(\[OTHERTEXT])/\1 \2/' 

但是回答你关于如何在grep中显示匹配项的问题,是的,可以使用选项-o实现。该选项将仅显示匹配行的匹配部分。然而,如果您使用

grep -o -e ".*\[TEXT\]" -e "\[OTHERTEXT\].*"

你将会得到匹配的部分,但是它们会在不同的行中。

另一种可能性是使用前瞻和后顾表达式,但是在你的情况下无法使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接