PHP Apache günlükleri için regex

3 Cevap php

Hy im PHP bu dize bölmek için çalışıyor.

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"

Bu nasıl ip in, tarihi, http yöntemi domainname'ini ve Tarayıcı ayırabilirsiniz?

3 Cevap

Bu günlük biçimi Apache’s combined log format gibi görünüyor. Bu normal ifade deneyin:

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

Aşağıdaki gibi eşleşen grupları şunlardır:

  1. Uzak IP adresi
  2. istek tarihi
  3. istek HTTP yöntemi
  4. User-Agent değer

Ama etki alanı var listede. İkinci alıntı dize Referer değerdir.

Bir düzenli ifade öğretici kontrol etmelisiniz. Ama burada cevap:

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];
}

Dikkat edin, bu günlüğüne alan adı ama HTTP referer değil.

İşte bazı Perl, PHP değil, ama kullanmak için regex aynıdır. Bu regex gördüğüm her şeyi ayrıştırmak için çalışır; istemciler, bazı tuhaf istekleri gönderebilirsiniz:

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;