2016-12-05 6 views
0

У меня есть большой файл журнала с идентификаторами пользователей и IP-адресами. Я пытаюсь определить лучший способ просмотра количества идентификаторов пользователей, к которым подключен определенный IP-адрес.Количество на основе нескольких столбцов

Первоначально я думал, что смогу сделать это через cut, sort и uniq в командной строке, но я не получаю вывод, который я желаю. Решение Python или bash было бы идеальным.

Ниже приведен пример файла:

eric 1.1.1.1 
eric 1.1.1.1 
brian 1.1.1.1 
jeff 1.1.1.1 
eric 2.2.2.2 
bob 3.3.3.3 
jeff 3.3.3.3 
eric 1.1.1.1 
eric 1.1.1.1 
eric 4.4.4.4 
peter 4.4.4.4 

я хотел выход, чтобы показать этот тип информации:

eric - 1.1.1.1, 2.2.2.2, 4.4.4.4 
brian - 1.1.1.1 
jeff - 1.1.1.1, 3.3.3.3 
bob - 3.3.3.3 
peter - 4.4.4.4 

Как:

1.1.1.1 - eric, brian, jeff 
2.2.2.2 - eric 
3.3.3.3 - bob, jeff 
4.4.4.4 - peter 

Поскольку он созревает, мне придется создать переменную для исключающих IP-адресов, где мы можем сказать, что 1.1.1.1 является NAT и доверяет, поэтому мы можем игнорировать i t, поскольку от него будет поступать множество пользователей.

Цените толчок в правильном направлении.

+0

Хм, я бы попытаться загрузить файл в 'pandas.DataFrame', то' grouby() 'колонки имя, и, наконец, получить уникальные значения каждой группы. – Jakub

+0

Вы хотите полный сценарий только некоторых рекомендаций? – timotree

+0

Должен ли вход быть как есть, или вы можете использовать кортежи или список или что-то еще? – OldBunny2800

ответ

4

Рассмотрим следующий сценарий, написанный в стиле ввода-вывода-вывода.

Некоторых примечания:

Модуль fileinput позволяет указать один входной файл в командной строке, несколько имен файлов, или нет файла на всех (он будет использовать стандартный ввод в этом случае).

defaultdict позволяет легко собирать наборы данных.

', ' join производит выделенные линии с разделителями-запятыми.

Использование выражения генератора (line.split() for line ...) вместо понимания списка [line.split() for line ...] сохраняет память (вы сказали, что это большие файлы). Если вы воспользовались пониманием списка, вы будете иметь все данные, хранящиеся в памяти дважды.

По мере созревания кода вы можете переключиться на argparse для управления новыми функциями, которые вы добавляете.

import fileinput 
import collections 

# Input the data 
raw_data = (line.split() for line in fileinput.input()) 

# Process the data 
name2ip = collections.defaultdict(set) 
ip2name = collections.defaultdict(set) 
for name, ip in raw_data: 
    name2ip[name].add(ip) 
    ip2name[ip].add(name) 

# Output the data 
for name, ips in name2ip.items(): 
    print '%s - %s'%(name, ', '.join(ips)) 

for ip, names in ip2name.items(): 
    print '%s - %s'%(ip, ', '.join(names)) 
+0

Большое спасибо за быстрый ответ Роб. Я буду играть с ним завтра. – Eric

+0

Еще раз спасибо за код. Я начал играть с ним сегодня, и он отлично справляется с предоставлением желаемого результата. Кроме того, благодарю вас за подробную информацию о том, что все это делает, это будет очень полезно в будущем. Единственное, что мне нужно сделать сейчас, это сортировать вывод, где имя с самыми уникальными IP-адресами отображается в то время и в разделе IP, тогда IP-адрес с наибольшим количеством имен отображается в то время. – Eric

+0

Я попытался запустить этот код в своих фактических журналах, и он не ответил «ValueError: слишком много значений для распаковки» в строке «для имени, ip в raw_data:». У меня есть ~ 20 log.gz файлов, каждая из которых содержит около 80 МБ. Я попытался просто сделать это с линией «zcat log_file.log.gz | code.py», когда я получил ошибку. Этот синтаксис отлично работает на моих небольших тестах. – Eric

Смежные вопросы