Форум русскоязычного сообщества Ubuntu


Хотите сделать посильный вклад в развитие Ubuntu и русскоязычного сообщества?
Помогите нам с документацией!

Автор Тема: Парсинг лог файла  (Прочитано 1512 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн mete0spb

  • Автор темы
  • Новичок
  • *
  • Сообщений: 3
    • Просмотр профиля
Парсинг лог файла
« : 24 Марта 2011, 20:48:15 »
Всем привет!
Есть лог файл со следующей структурой:
поле1=значенние1:поле2=значенеи2:поле3=значение3
поле1=значенние1:поле2=значенеи2:поле3=значение3
...
поле1=значенние1:поле2=значенеи2:поле3=значение3
Причём отсортирован он по значению2 (это цифра) в порядке убывания, и строк, где это значение2 повторяется много.
Нужно для тех групп строк, для которых значение2 повторяется посчитать среднее по значению3, вставив его как новую строку после каждой одинаковой группы повторяющихся значений2. Уфф.
Пример:
a=1:b=1:c=12
a=2:b=1:c=10
a=3:b=2:c=5
a=4:b=2:c=10
a=5:b=2:c=20
Нужно получить как то так:
a=1:b=1:c=12
a=2:b=1:c=10
b=1:avg_c=11
a=3:b=2:c=10
a=4:b=2:c=10
a=5:b=2:c=10
b=2:avg_c=10

Пробовал решать её с помощью AVG и SED но хоть как то далеко не продвинулся.
Думалки не хватает, я в этом не профан)
Подскажите пожалуйста, буду признателен.

Оффлайн Мангуст

  • Любитель
  • *
  • Сообщений: 98
    • Просмотр профиля
Re: Парсинг лог файла
« Ответ #1 : 25 Марта 2011, 06:26:57 »
Кажется, что с помощью шелл и подручных средств - тяжеловато будет. Как бы их разделить на группы и по группам просчитать?  :-\

А так надо выделять первую и последнюю строчку - неэлегантное решение (вроде-бы) на Перл:

(Нажмите, чтобы показать/скрыть)

« Последнее редактирование: 25 Марта 2011, 11:01:42 от Мангуст »

Оффлайн mete0spb

  • Автор темы
  • Новичок
  • *
  • Сообщений: 3
    • Просмотр профиля
Re: Парсинг лог файла
« Ответ #2 : 25 Марта 2011, 06:51:51 »
Собственно алгоритм тут понятен.
Пока текущее значение2=предыдущему значению2 накапливаем значение3 и увеличиваем счётчик значения3.
Как только отличается делим накопленное на наш счётчик и всё обнуляем.
На C/PHP и др. делается за 5 минут.
Я пробовал аналогичное провернуть с AWK, но в один проход даже не смог получить нормальные распарсенные значения.
Моей думалки тут не хватает  :'(

Оффлайн spk-ubuntu

  • Активист
  • *
  • Сообщений: 502
    • Просмотр профиля
Re: Парсинг лог файла
« Ответ #3 : 25 Марта 2011, 09:18:49 »
в первом приближении что-то вроде (awk):
BEGIN {
  FS=":"
}

{
  print($0) # выводим текущую строку

  n=split($2, array_b, "=")
  cur_b=array_b[2] # текущее значение b
  n=split($3, array_c, "=")
  cur_c=array_c[2] # текущее значение c

  if (NR==1) {
    # это первая строка; зададим значения переменных
    val_b=cur_b
    sum_c=0
    num_c=0
  }

  if (cur_b!=val_b) {
    # значение b в тексте поменялось (было "b=N", стало "b=M")
    avg_c = sum_c/num_c
    print("b=" val_b ":avg_c=" avg_c)
    val_b=cur_b
    sum_c=0
    num_c=0
  }

  sum_c=sum_c+cur_c
  num_c++
}

END {
  if (num_c!=0) {
    avg_c = sum_c/num_c
    print("b=" val_b ":avg_c=" avg_c)
  }
}

Оффлайн alexander.pronin

  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Парсинг лог файла
« Ответ #4 : 25 Марта 2011, 14:22:56 »

cat ./test
a=1:b=1:c=12
a=2:b=1:c=10
a=3:b=2:c=5
a=4:b=2:c=10
a=5:b=2:c=20
a=6:b=3:c=2

cat ./parseLog.py
#! /usr/bin/env python
#!-*-coding: UTF-8-*-
import sys, os
import re
lines=open('./test', 'rb').readlines()# читаем файл построчно (это первое деление)
f2_old=''
sum=0
counter=0
for line in lines:
fields=line.split(':')
f2=fields[1].split('=')
f3=fields[2].split('=')
if f2_old!=f2[1]:
if counter!=0:
print 'b=',f2_old,'  avg_c=',sum/counter
f2_old=f2[1]
sum=0
counter=0
sum+=int(f3[1])
counter+=1
print line


 ./parseLog.py
a=1:b=1:c=12

a=2:b=1:c=10

b= 1   avg_c= 11
a=3:b=2:c=5

a=4:b=2:c=10

a=5:b=2:c=20

b= 2   avg_c= 11
a=6:b=3:c=2
 
PS. Можно чуть подчистить вывод и последнюю выдачу.
« Последнее редактирование: 25 Марта 2011, 14:26:46 от alexander.pronin »

Оффлайн mete0spb

  • Автор темы
  • Новичок
  • *
  • Сообщений: 3
    • Просмотр профиля
Re: Парсинг лог файла
« Ответ #5 : 25 Марта 2011, 16:32:16 »
Спасибо всем огромное. Реально помогли. :coolsmiley:
Особенно spk-ubuntu.
Этот способ мне больше всего понравился.
Единственное, строчку: print($0) # выводим текущую строку нужно в конец, после if-ов переместить.
Так логично всё выглядит, что думаешь, как же я сам не додумался до этого? =)

 

Страница сгенерирована за 0.058 секунд. Запросов: 26.