campos entre aspas na entrada para o awk

0

Eu estou tentando processar um arquivo de log do servidor web no awk. Como

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) ...."
  • O campo 1,2,3 é separado apenas por espaço em branco.
  • Campo 4, a data é incluída em []
  • O campo 5, o URL, é colocado em ""
  • O campo 6,7 é separado por espaço em branco. (Inteiros)
  • Campo 8,9 o referenciador e useragent é colocado em ""

Como posso analisar esses campos?

    
por Lenne 24.02.2015 / 13:30

2 respostas

0

Eu escolheria um delimitador "principal" e usaria split() em alguns dos campos:

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) ....
    
por 24.02.2015 / 15:05
0

Outra solução é analisar o log:

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

Observe que as cotações incorporadas eliminarão o analisador. Há outras melhorias a serem feitas, mas espero que você tenha a idéia.

No entanto, acho que, se você precisar de mais energia, seria melhor verificar analisadores de arquivos de log dedicados ou uma linguagem de script mais eficiente. Por exemplo, o Perl tem um módulo Text :: Balanced que pode extrair strings citadas e entre colchetes, e geralmente faz A Coisa Certa com citações embutidas e outras dificuldades. (BTW, um script em Perl usando Text :: Balanced seria muito semelhante ao acima!)

    
por 25.02.2015 / 10:03

Tags