Как отсортировать список, используя grep, чтобы показать количество уникальных вхождений на основе предварительно определенного списка? - PullRequest
2 голосов
/ 18 апреля 2020

Итак, допустим, у меня есть список, который выглядит следующим образом

example.txt:

2010-01-06 15:03:14 57.55.24.13 user1
2010-01-07 20:02:14 69.54.12.36 user2
2010-01-08 12:34:34 127.21.159.2 user3
2010-01-08 02:43:45 116.40.11.179 user1 

В списке есть несколько заданных пользователей и IP-адрес адреса, которые они использовали. То, что я хочу сделать, это найти количество уникальных IP-адресов, с которых каждый пользователь вошел в систему. Таким образом, в предыдущем примере user1 вернул бы значение 2. Однако, если user1 снова вошел в систему с 116.40.11.179, результатом все равно будет 2, поскольку это не уникальный ip.

Я попытался составить список имен пользователей.

userlist.txt:

user1
user2
user3

Затем я пытаюсь передать его в grep с чем-то как

grep example.txt | uniq -c | wc -l < userlist.txt

, но это явно не так хорошо. Есть идеи?

Ответы [ 5 ]

2 голосов
/ 18 апреля 2020

Не могли бы вы попробовать следующее.

awk '
!seen[$NF OFS $(NF-1)]++{
  user[$NF]++
}
END{
  for(key in user){
    print key,user[key]
  }
}
'  Input_file

Вывод будет следующим.

user1 2                                                                                                                       
user2 1                                                                                                                       
user3 1 
1 голос
/ 18 апреля 2020

Инструментом для выполнения этой операции является uniq . Вам необходимо применить uniq дважды: первый раз для группировки записей example.txt по пользователю и IP, второй для подсчета.

Так что нет необходимости перекодировать его в AWK, даже если это можно сделать очень красивым способом. Однако я буду использовать AWK для изменения порядка полей:

awk '{print $4, $3}' example.txt | sort | uniq | awk '{print $1}' | uniq -c

Нет необходимости в отдельном userlist.txt файле.

1 голос
/ 18 апреля 2020

С GNU awk для массивов массивов:

$ awk '{usrs_ips[$4][$3]} END{for (usr in usrs_ips) print usr, length(usrs_ips[usr])}' file
user1 2
user2 1
user3 1

С awk, который поддерживает длину (массив):

$ sort -k4,4 file | awk '
    $4 != prev {if (NR>1) print prev, length(ips); prev=$4; delete ips }
    { ips[$3] }
    END { print prev, length(ips) }
'
user1 2
user2 1
user3 1

С любым awk:

$ sort -k4,4 file | awk '
    $4 != prev { if (NR>1) print prev, cnt; prev=$4; delete seen; cnt=0 }
    !seen[$3]++ { cnt++ }
    END { print prev, cnt }
'
user1 2
user2 1
user3 1

Последние 2 имеют преимущество перед первым и другими опубликованными решениями, заключающимися в том, что они не хранят каждую комбинацию пользователь + ip в памяти, но это будет иметь значение, только если ваш входной файл будет огромным.

1 голос
/ 18 апреля 2020
awk '
{
    u = $4
    ip = $3
    if (!s[u,ip]++)
        cnt[u]++
}
END {
    for (u in cnt)
        print u, cnt[u]
}
' input.file

Выходы

user1 2
user2 1
user3 1
0 голосов
/ 18 апреля 2020

Пример, отличный от awk, с использованием GNU datamash, действительно полезный инструмент для выполнения операций групп столбчатых данных, таких как:

$ datamash -Ws -g4 countunique 3 < example.txt
user1   2
user2   1
user3   1

Для каждой группы с тем же значением в 4-м столбце выводит число уникальных вхождений значений в третьем столбце.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...