从 grep 结果中 grep 一个子字符串

从 grep 结果中 grep 一个子字符串

给定一个日志文件,我通常会做这样的事情:

grep 'marker-1234' filter_log

在模式中使用 '' 或 "" 或者不包含任何内容有什么区别?

上面的 grep 命令将产生数千行;这正是我想要的。在这些行中,通常有一块我想要的数据。有时,我会使用 awk 打印出我想要的字段。在这种情况下,日志格式会发生变化,我不能完全依赖位置,更不用说,实际记录的数据可以将位置向前推进。

为了使这一点更容易理解,假设日志行包含一个 IP 地址,这就是我所想要的,所以我以后可以通过管道将其排序和唯一,并获得一些计数。

例如:

2010-04-08 some logged data, indetermineate chars - [marker-1234] (123.123.123.123) from: [email protected] to [email protected] [stat-xyz9876]

第一个 grep 命令将给我数千行类似上面的内容,从那里,我想将它通过管道传输到某个东西,可能是sed,它可以从中提取出一个模式,然后只打印该模式。

对于此示例,使用 IP 地址就足够了。我试过了。无法sed理解 [0-9]{1,3}。作为模式?我不得不使用 [0-9][0-9][0-9]。这产生了奇怪的结果,直到创建了整个模式。

这并不特定于 IP 地址,模式会改变,但我可以将其用作学习模板。

谢谢你们。

答案1

我不知道你用的是什么操作系统,但在 FreeBSD 7.0+ 上,grep 有一个-o选项可以只返回与模式匹配的部分。所以你可以
grep "marker-1234" filter_log | grep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

从“filter_log”中返回 IP 地址列表...

这在我的系统上运行良好,但我不知道你的 grep 版本支持什么。

答案2

只需一个命令即可完成所有这些操作awk。无需使用任何其他工具

$ awk '/marker-1234/{for(o=1;o<=NF;o++){if($o~/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)print $o }  }' file
(123.123.123.123)

答案3

你可以将第二个grep稍微缩短一点,如下所示:

grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'

回答你的第一个问题,双引号允许 shell 执行各种操作,例如变量扩展,但可以保护某些元字符免于转义。单引号可防止 shell 执行这些扩展。不使用引号会让事情变得毫无头绪。

$ empty=""
$ text1="some words"
$ grep $empty some_file
(It seems to hang, but it's just waiting for input since it thinks "some_file" is 
the pattern and no filename was entered, so it thinks input is supposed to come
from standard input. Press Ctrl-d to end it.)
$ grep "$empty" some_file
(The whole file is shown since a null pattern matches everything.)
$ grep $text1 some_file
grep: words: No such file or directory
some_file:something
some_file:some words
(It sees the contents of the variable as two words, the first is seen as the 
pattern, the second as one file and the filename as a second file.)
$ grep "$text1" some_file
some_file:some words
(Expected results.)
$ grep '$text1' some_file
(No results. The variable isn't expanded and the file doesn't contain a
string that consists of literally those characters (a dollar sign followed
by "text1"))

您可以在“引用”部分了解更多信息man bash

答案4

查找xargs命令。你应该能够执行如下操作:

grep ‘marker-1234’ filter_log|xargs grep “(”|cut -c1-15

这可能不完全正确,但这xargs是您想要使用的命令

相关内容