【问题标题】:How to parse Apache logs using a regex in PHP如何在 PHP 中使用正则表达式解析 Apache 日志
【发布时间】:2011-01-14 08:45:51
【问题描述】:

我正在尝试在 PHP 中拆分此字符串:

11.11.11.11 - - [25/Jan/2000:14:00:01 +0100] "GET /1986.js HTTP/1.1" 200 932 "http://domain.com/index.html" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"

如何将其拆分为 IP、日期、HTTP 方法、域名和浏览器?

【问题讨论】:

标签: php regex


【解决方案1】:

这个日志格式似乎是Apache’s combined log format。试试这个正则表达式:

/^(\S+) \S+ \S+ \[([^\]]+)\] "([A-Z]+)[^"]*" \d+ \d+ "[^"]*" "([^"]*)"$/m

匹配组如下:

  1. 远程 IP 地址
  2. 请求日期
  3. 请求HTTP方法
  4. User-Agent

但该域未在此处列出。第二个带引号的字符串是Referer 值。

【讨论】:

  • @streetparade:使用preg_match_all,你会得到所有匹配:preg_match_all('…', $str, $matches)
  • 这个正则表达式无法编译...缺少圆括号;)
  • 这个错了,auth-user字段(第三个,%u)可以包含空格。
  • @JulienPalard 您介意提供更新建议吗?
【解决方案2】:

您应该查看正则表达式教程。但这里是答案:

if (preg_match('/^(\S+) \S+ \S+ \[(.*?)\] "(\S+).*?" \d+ \d+ "(.*?)" "(.*?)"/', $line, $m)) {
  $ip = $m[1];
  $date = $m[2];
  $method = $m[3];
  $referer = $m[4];
  $browser = $m[5];
}

注意,不是日志中的域名,而是 HTTP 引用者。

【讨论】:

    【解决方案3】:

    这里是一些 Perl,不是 PHP,但使用的正则表达式是相同的。这个正则表达式可以解析我所看到的一切;客户端可以发送一些奇怪的请求:

    my ($ip, $date, $method, $url, $protocol, $alt_url, $code, $bytes,
            $referrer, $ua) = (m/
        ^(\S+)\s                    # IP
        \S+\s+                      # remote logname
        (?:\S+\s+)+                 # remote user
        \[([^]]+)\]\s               # date
        "(\S*)\s?                   # method
        (?:((?:[^"]*(?:\\")?)*)\s   # URL
        ([^"]*)"\s|                 # protocol
        ((?:[^"]*(?:\\")?)*)"\s)    # or, possibly URL with no protocol
        (\S+)\s                     # status code
        (\S+)\s                     # bytes
        "((?:[^"]*(?:\\")?)*)"\s    # referrer
        "(.*)"$                     # user agent
    /x);
    die "Couldn't match $_" unless $ip;
    $alt_url ||= '';
    $url ||= $alt_url;
    

    【讨论】:

      【解决方案4】:
      // # Parses the NCSA Combined Log Format lines:
      $pattern = '/^([^ ]+) ([^ ]+) ([^ ]+) (\[[^\]]+\]) "(.*) (.*) (.*)" ([0-9\-]+) ([0-9\-]+) "(.*)" "(.*)"$/';
      

      用法:

      if (preg_match($pattern,$yourstuff,$matches)) {
      
          //# puts each part of the match in a named variable
      
          list($whole_match, $remote_host, $logname, $user, $date_time, $method, $request, $protocol, $status, $bytes, $referer, $user_agent) = $matches;
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-02
        • 1970-01-01
        • 2011-09-12
        • 1970-01-01
        • 1970-01-01
        • 2019-08-24
        • 1970-01-01
        相关资源
        最近更新 更多