Я пытаюсь обработать файл журнала веб-сервера в awk. подобно

123.222.333.444  - - [24/Feb/2015:13:09:19 +0100] "GET / HTTP/1.1" 200 15852 "https://www.google.dk/" "Mozilla/5.0 (Windows NT 6.1) ...."
  • Поля 1,2,3 просто разделены пробелами.
  • Поле 4, дата заключена в []
  • Поле 5 URL, заключено в ""
  • Поле 6,7 просто разделено пробелами. (Целые)
  • Поле 8,9 реферера и идентификатора пользователя заключено в ""

Как я могу разобрать эти поля?

2 ответа2

0

Я бы выбрал один "основной" разделитель и использовал split() для некоторых полей:

awk -F '"' '
{
  http_cmd = $2
  url = $4
  ua = $6
  split($1, a, /[][]/); date = a[2]
  split(a[1], b, " "); ip = b[1]; f2 = b[2]; f3 = b[3]
  split($3, c, " "); code = c[1]; size = c[2]
  OFS = "\n"
  print ip, f2, f3, date, http_cmd, code, size, url, ua
}' << END
123.222.333.444  - - [24/Feb/2015:13:09:19 +0100] "GET / HTTP/1.1" 200 15852 "https://www.google.dk/" "Mozilla/5.0 (Windows NT 6.1) ...."
END
123.222.333.444
-
-
24/Feb/2015:13:09:19 +0100
GET / HTTP/1.1
200
15852
https://www.google.dk/
Mozilla/5.0 (Windows NT 6.1) ....
0

Другое решение состоит в том, чтобы разобрать журнал:

function consume(pat) {
    sub(/^[ \t]+/, "")                      # strip leading whitespace
    if (!match($0, pat)) return
    s = substr($0, p, RLENGTH)              # extract part matching regex pattern
    $0 = substr($0, RSTART + RLENGTH + 1)   # strip matched part
    return s
}
BEGIN {
    # regular expressions to match ...
    nonblank = "[^ \t]+"                    # a sequence of non-whitespace characters
    quoted_string = "\"[^\"]+\""            # a ""-quoted string
    bracketed_string = "\\[[^]]+\\]"        # a []-quoted string
}
{ print
  array["ip"] = consume(nonblank)
  array["identity"] = consume(nonblank)
  array["userid"] = consume(nonblank)
  array["time"] = consume(bracketed_string)
  array["request"] = consume(quoted_string)
  array["status"] = consume(nonblank)
  array["size"] = consume(nonblank)
  array["referer"] = consume(quoted_string)
  array["agent"] = consume(quoted_string)
  for (key in array) printf "  %10s: %s\n", key, array[key]
}

Обратите внимание, что встроенные кавычки скинут парсер. Есть и другие улучшения, но я надеюсь, что вы поняли идею.

Тем не менее, я думаю, что если вам нужно больше энергии, лучше проверить специализированные парсеры лог-файлов или более мощный язык сценариев. Например, в Perl есть модуль Text::Balanced, который может извлекать строки в кавычках и в скобках, и, как правило, выполняет The Right Thing со встроенными кавычками и другими трудностями. (Кстати, скрипт на Perl с использованием Text::Balanced будет выглядеть очень похоже на выше!)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .