Как анализировать журналы Apache с помощью регулярного выражения в PHP

Я пытаюсь разбить эту строку в 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, доменное имя и браузер?

Этот формат журнала, по-видимому, является комбинированным форматом журнала Apache . Попробуйте это регулярное выражение:

 /^(\S+) \S+ \S+ \[([^\]]+)\] "([AZ]+)[^"]*" \d+ \d+ "[^"]*" "([^"]*)"$/m 

Соответствующие группы:

  1. удаленный IP-адрес
  2. Дата заказа
  3. запрос HTTP-метода
  4. Значение User-Agent

Но домен там не указан. Вторая цитированная строка – это значение Referer .

Вы должны проверить учебник регулярного выражения. Но вот ответ:

 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-референт.

Вот несколько 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; 
 // # 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; }