16

我想从我的服务器日志中获取“ 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 -

我只想显示:你好ss

有什么办法可以做到吗?

4

6 回答 6

20

假设你有 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,那可以大大简化:

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

这里的底线是,您当然不需要管道来完成此操作。 grep或者sed单独就足够了。

于 2012-06-10T19:58:56.540 回答
11

在这种情况下,由于日志文件具有已知结构,一个选项是使用cut拉出第 7 列(字段默认由制表符表示)。

grep GET log.txt | cut -f 7 
于 2012-06-10T19:43:40.553 回答
5

我试图这样做并遇到了这个链接:https ://www.unix.com/shell-programming-and-scripting/153101-print-next-word-after-found-pattern.html

总结:使用 grep 查找匹配行,然后使用 awk 查找模式并打印下一个字段:

grep pattern logfile | \
  awk '{for(i=1; i<=NF; i++) if($i~/pattern/) print $(i+1)}'

如果您想知道独特的出现:

grep pattern logfile | \
  awk '{for(i=1; i<=NF; i++) if($i~/pattern/) print $(i+1)}' | \
  sort | \
  uniq -c
于 2018-02-20T19:05:20.530 回答
4

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

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

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

于 2014-03-07T04:06:22.310 回答
2

使用管道通常比使用单个复杂的正则表达式更容易。这适用于您提供的数据:

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

此管道返回以下结果:

hello
ss

当然还有其他方法可以完成这项工作,但这显然适用于提供的语料库。

于 2012-06-10T19:51:15.830 回答
1
gawk '{match($7,/\/(\w+)/,a);} length(a[1]){print a[1]}' log.txt
hello
ss

如果你有gawk那么上面的命令将使用match函数来使用正则表达式选择所需的值并将其存储到一个数组a中。

于 2017-03-28T09:59:18.397 回答