campi racchiusi tra virgolette in input per awk


0

Sto cercando di elaborare un file di log del server web in awk. Piace

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) ...."
  • Il campo 1,2,3 è appena separato da uno spazio bianco.
  • Campo 4, la data è racchiusa tra []
  • Il campo 5 dell'URL è racchiuso tra ""
  • Il campo 6,7 è appena separato da uno spazio bianco. (interi)
  • Il campo 8,9 referer e useragent è racchiuso tra ""

Come posso analizzare questi campi?

Risposte:


0

Vorrei scegliere un delimitatore "principale" e utilizzarlo split()su alcuni dei campi:

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

Un'altra soluzione è analizzare il registro:

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

Si noti che le virgolette incorporate elimineranno il parser. Ci sono altri miglioramenti da apportare, ma spero che tu abbia avuto l'idea.

Penso, tuttavia, che se hai bisogno di più potenza, sarebbe meglio controllare i parser di file di registro dedicati o un linguaggio di scripting più potente. Ad esempio, Perl ha un modulo Text :: Balanced che può estrarre stringhe tra virgolette e tra parentesi, e generalmente fa la cosa giusta con virgolette incorporate e altre difficoltà. (A proposito, uno script in Perl che usa Text :: Balanced sarebbe molto simile al precedente!)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.