Невозможно получить uniq - c в цикле while - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь отсортировать файл журнала, получить общее количество уникальных IP-адресов и что-то сделать с теми, которые появляются> n. это моя первая команда:

$ grep -B 1 "foobar" ip.log | grep "IP Address" > ip_count.log

, которая выводит:

IP Address    : 133.55.39.56
IP Address    : 116.243.70.151
IP Address    : 117.46.13.194
IP Address    : 115.179.82.10
IP Address    : 13.123.2.123
IP Address    : 13.123.2.123
IP Address    : 13.123.2.123
IP Address    : 13.123.2.123
IP Address    : 13.123.2.123
IP Address    : 13.123.2.123
IP Address    : 13.123.2.123
IP Address    : 13.123.2.123
IP Address    : 13.123.2.123
IP Address    : 33.123.2.123
IP Address    : 33.123.2.123
IP Address    : 33.123.2.123
IP Address    : 33.123.2.123
IP Address    : 33.123.2.123
IP Address    : 33.123.2.123

, если я сделаю это, я получу правильный счет:

$ awk '{print $4}' ip_count.log | uniq -c
      1 133.55.39.56
      1 116.243.70.151
      1 117.46.13.194
      1 115.179.82.10
      9 13.123.2.123
      6 33.123.2.123

, но если я сделаю это это я не знаю:

$ while read -r line ; do c=$(echo $line | awk '{print $4}' | \
uniq -c | awk '{print $1}') ; if [[ $c -gt 1 ]]; then echo "$line" ; \
fi ; done < ip_count.log

1 133.55.39.56
1 116.243.70.151
1 117.46.13.194
1 115.179.82.10
1 13.123.2.123
1 13.123.2.123
1 13.123.2.123
1 13.123.2.123
1 13.123.2.123
1 13.123.2.123
1 13.123.2.123
1 13.123.2.123
1 13.123.2.123
1 33.123.2.123
1 33.123.2.123
1 33.123.2.123
1 33.123.2.123
1 33.123.2.123
1 33.123.2.123

Я не уверен, что я делаю неправильно в l oop, так что, возможно, кто-то может сказать мне. в любом случае, возможно, есть какой-то лучший способ объединить все это в одну команду, поэтому любые советы будут полезны, спасибо.

Ответы [ 2 ]

0 голосов
/ 20 марта 2020

Когда вы читаете файл в l oop, он выполняет команду строка за строкой.

awk '{print $4}' ip_count.log | uniq -c

В приведенном выше примере все записи считываются из stdin и обрабатываются.

при выполнении l oop while read -r line ваша переменная $line содержит только 1 запись всего файла.

Вы можете сделать это одной командой awk, используя ассоциативный массив.

Альтернативное решение с использованием awk

$awk -F':' '{ count=1; a[$2]=a[$2]+count} END {for (i in a) if (a[i]>1 )print i, a[i]} '  ip_count.log
 33.123.2.123 6
 13.123.2.123 9
$

Объяснение:

-F':' -> мы устанавливаем разделитель пользовательских полей как :
count=1; -> Инициализируем переменную как значение по умолчанию 2
a[$2]=a[$2]+count -> Создаем ассоциативный массив с $2 в качестве индекса и считать как значения.
END -> Дождаться завершения { } выполнения блока кода
{for (i in a) if (a[i]>1 )print i, a[i]} -> L oop через каждое значение в массиве

Также, Рекомендуется передавать отсортированный ввод команде uniq.

Например:

$echo -e "a\na\nb\na"  
a
a
b
a
$echo -e "a\na\nb\na"  | uniq -c
      2 a
      1 b
      1 a
$echo -e "a\na\nb\na"  | sort | uniq -c
      3 a
      1 b
$

0 голосов
/ 20 марта 2020

Кажется, нет необходимости в l oop:

uniq -c ip_count.log | awk '$1 > 1 { print $1" "$5 }'
...