Фильтрация нескольких конкретных значений из строки Log в Linux - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть журналы с такими типами строк:

"09/Feb/2019:11:25:51 +0000" client=10.0.0.148 method=GET request="GET /flask2 HTTP/1.1" [...] request_time=0.011 [...] upstream_header_time=0.010

Мне удалось извлечь из журнала единичные значения (например, только время запроса), например:

cat <logfile> | sed -n -e 's/^.*request_time=//p' | sed -n -e 's/ .*$//p'

Я хотел бы отфильтровать значения так, чтобы я получил следующее:

"09/Feb/2019:11:25:51 +0000" "GET /flask2 HTTP/1.1" 0.011

Это:

<time> <request> <request-time>

Как бы это было достигнуто?

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Рассмотрим это, используя GNU awk для FPAT:

$ cat tst.awk
BEGIN {
    FPAT="([^[:space:]=]+=)?(\"[^\"]+\"|[^[:space:]]+)"
}
{
    for (i=1; i<=NF; i++) {
        print i, "<" $i ">"
    }
}

$ awk -f tst.awk file
1 <"09/Feb/2019:11:25:51 +0000">
2 <client=10.0.0.148>
3 <method=GET>
4 <request="GET /flask2 HTTP/1.1">
5 <[...]>
6 <request_time=0.011>
7 <[...]>
8 <upstream_header_time=0.011>

Учитывая вышеописанный метод анализа вашего ввода, вы можете легко определить, какие поля вы хотите вывести, и даже ссылаться на них просто по имени или позиции, например:

$ cat tst.awk
BEGIN {
    FPAT="([^[:space:]=]+=)?(\"[^\"]+\"|[^[:space:]]+)"
}
{
    f["time"] = $1
    for (i=2; i<=NF; i++) {
        tag = val = $i
        sub(/=.*/,"",tag)
        sub(/^[^=]+=/,"",val)
        f[tag] = val
    }

    print f["time"], f["request"], f["request_time"]
}

$ awk -f tst.awk file
"09/Feb/2019:11:25:51 +0000" "GET /flask2 HTTP/1.1" 0.011

Подумайте о том, как легко будет изменить в будущем, если вы захотите дополнительно напечатать IP-адрес и метод клиента в CSV в определенном порядке полей со всеми полями, заключенными в двойные кавычки или простоо чем-либо еще, например:

$ cat tst.awk
BEGIN {
    FPAT="([^[:space:]=]+=)?(\"[^\"]+\"|[^[:space:]]+)"
    OFS=","
}
{
    f["time"] = $1
    for (i=2; i<=NF; i++) {
        tag = val = $i
        sub(/=.*/,"",tag)
        sub(/^[^=]+=/,"",val)
        gsub(/^"|"$/,"",val)
        f[tag] = "\"" val "\""
    }

    print f["time"], f["request"], f["request_time"], f["client"], f["method"]
}

$ awk -f tst.awk file
"09/Feb/2019:11:25:51 +0000","GET /flask2 HTTP/1.1","0.011","10.0.0.148","GET"
0 голосов
/ 12 февраля 2019

Попробуйте этот Perl однострочный

perl -ne ' /(^.+?").+?request=(.+?").+?request_time=(\S+)/ and print "$1 $2 $3" '

с заданными входами

$ cat  req.logs
"09/Feb/2019:11:25:51 +0000" client=10.0.0.148 method=GET request="GET /flask2 HTTP/1.1" [...] request_time=0.011 [...] upstream_header_time=0.010


$ perl -ne ' /(^.+?").+?request=(.+?").+?request_time=(\S+)/ and print "$1 $2 $3" ' req.logs
"09/Feb/2019:11:25:51 +0000" "GET /flask2 HTTP/1.1" 0.011
$
0 голосов
/ 12 февраля 2019

с grep

$ grep -oP '^"[^"]+"|request(|_time)=\K("[^"]+"|\S+)' file | paste -s

"09/Feb/2019:11:25:51 +0000"    "GET /flask2 HTTP/1.1"  0.011

в зависимости от результата вы получаете запрос , а не метод .

...