在每行匹配后使用grep获取下一个WORD

我想从我的服务器日志中获取“ GET ”查询。

例如,这是服务器日志

1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] code 404, message File not fo$ 1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] "GET /hello HTTP/1.1" 404 - 1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] code 404, message File not fo$ 1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] "GET /ss HTTP/1.1" 404 - 

当我用简单的grep或awk尝试时,

 Adi:~ adi$ awk '/GET/, /HTTP/' serverlogs.txt 

它发出

 1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] "GET /hello HTTP/1.1" 404 - 1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] "GET /ss HTTP/1.1" 404 - 

我只想显示: helloss

有什么办法可以做到吗?

Solutions Collecting From Web of "在每行匹配后使用grep获取下一个WORD"

假设你有gnu grep,你可以使用perl风格的正则表达式做一个积极的向后看:

 grep -oP '(?<=GET\s/)\w+' file 

如果你没有gnu grep,那么我建议只使用sed:

 sed -n '/^.*GET[[:space:]]\{1,\}\/\([-_[:alnum:]]\{1,\}\).*$/s//\1/p' file 

如果你碰巧有gnu sed(如果你没有gnu grep,但是确实有gnu sed会很奇怪),那可以大大简化:

 sed -n '/^.*GET\s\+\/\(\w\+\).*$/s//\1/p' file 

这里的底线是,你当然不需要管道来完成这个任务。 grepsed就足够了。

在这种情况下,由于日志文件具有已知结构,因此一种选择是使用cut来拉出第七列(字段默认由选项卡表示)。

 grep GET log.txt | cut -f 7 

如果使用grep,请使用管道:

 grep -o /he.* log.txt | grep -o [^/].* grep -o /ss log.txt | grep -o [^/].* 

[^ /]表示从grep输出中提取^符号后面的字母

使用管道而不是单个复杂的正则表达式通常更容易。 这对您提供的数据有效:

 fgrep GET /tmp/foo | egrep -o 'GET (.*) HTTP' | sed -r 's/^GET \/(.+) HTTP/\1/' 

该管道返回以下结果:

 hello ss 

当然还有其他的方法可以完成这个工作,但是这个提供的语料库显然是有效的。

 gawk '{match($7,/\/(\w+)/,a);} length(a[1]){print a[1]}' log.txt hello ss 

如果你有gawk那么上面的命令将使用match功能,使用正则表达式选择所需的值,并将其存储到数组a