grep частичный IP-адрес из файла

Тот, у кого больше опыта работы с внутренностями Linux, может меня поправить, но из документации похоже, что они хотят оставить за собой право реализовать sleep()через alarm(), что временно установит обработчик для SIGALRM.

Это не тот SIGCHLD, который упоминается в фактической документации, но он все равно подпадает под «MT -Небезопасный сигнал».

1
25.08.2021, 07:52
2 ответа

Если я вас правильно понял, вы хотите проанализировать список IP-адресов и определить, к какой сети класса B или C они принадлежат. Если какая-либо такая сеть встречается более 10 раз, вы хотите напечатать IP-адрес вместе с сетью, к которой он принадлежит, в нотации

.
A.B.C.D   A.B.0.0/16  n

или

A.B.C.D   A.B.C.0/24  n

соответственно в выходной файл spam.lst, где n— фактическое количество вхождений в соответствующей подсети.

Предлагаю следующую awkпрограмму для задачи (назовем ееsort.awk):

#!/bin/awk -f

BEGIN{
    FS=OFS="."
}

NF==4{
    if (FNR==NR) {
        NF=cl
        count[$0]++
        next
    }
    for (n in count) {
        if (index($0,n)==1) {
            if (count[n]<=th) next
            printf "%s %s",$0,n
            for (i=cl;i<4;i++) printf ".0"
            printf "/%d %d\n",8*cl,count[n]
        }
    }
}

Вы бы назвали это следующим образом:

awk -v cl=2 -v th=1 -f sort.awk ips.txt ips.txt> spam.lst

Обратите внимание, что входной файл обрабатывается два раза и, следовательно, два раза появляется в качестве аргумента для awk!

Программа работает следующим образом:

  • Вы указываете класс сети CIDR как awkпеременную clкак либо 2для сети класса B, либо 3для сети класса C.
  • Вы указываете минимальное количество вхождений, начиная с которого вы хотите заблокировать всю подсеть, как awkпеременную th.
  • Программа устанавливает разделители ввода и вывода равными ., чтобы разделить входные строки в .на поля.
  • Скрипт учитывает только строки, содержащие ровно 4 поля. (Минимальная проверка работоспособности для IP-адресов)
  • В первом проходе(FNRсчетчик строк файла -равен NR, глобальному счетчику строк ), мы регистрируем обнаруженные подсети. Для каждой строки номер поля сокращается до значения в cl, чтобы сократить его до сетевого «базового адреса» класса B или C. Затем счетчик для этого (заново сгенерированного )базового адреса в массиве countувеличивается, и обработка переходит к следующей строке.
  • Во втором проходе мы перебираем все индексы из count(, т. е. все подчиненные -сети, зарегистрированные в первом проходе ), чтобы увидеть, начинается ли IP в текущей строке с этого адрес подсети. Если связанный счетчик больше порогового значения, мы выводим текущий IP-адрес,затем базовый адрес, дополненный справа .0и добавленной маской сети в нотации CIDR, и, наконец, количество вхождений.

Вывод для cl=2, th=1и приведенный вами пример списка IP-адресов будет выглядеть как

108.61.115.213 108.61.0.0/16 2
108.61.199.100 108.61.0.0/16 2
138.68.224.206 138.68.0.0/16 2
138.68.235.36 138.68.0.0/16 2
148.66.129.250 148.66.0.0/16 2
148.66.130.114 148.66.0.0/16 2

Первоначальное предложение предназначалось для интеграции в существующий сценарий и выглядело следующим образом:

awk -v cl=2 -v nw="8.6.0.0" -F'.' 'BEGIN{split(nw,ref,/\./)} NF==4{for (i=1;i<=cl;i++) {if ($i!=ref[i]) next} printf "%s %s/%d\n",$0,nw,8*cl}' ips.txt

Здесь мы проанализируем список IP-адресов, чтобы проверить, попадают ли они в ту же сеть, что и данный базовый сетевой адрес, указанный с помощью awkпеременной nw.

  • В начале базовый IP эталонной сети разбивается по полям в массив ref.
  • Для каждой обнаруженной строки программа сначала проверяет, содержит ли она 4 поля (Минимальная проверка работоспособности для IP ). Если это так, он сравнивает первые clполя текущей строки и эталонного IP-адреса. Если какой-либо из них не совпадает, строка пропускается и обработка переходит к следующей строке. Если все соответствующие поля совпадают, печатается IP-адрес, за которым следует сеть в нотации CIDR.
1
25.08.2021, 09:12

В соответствии с исходным вопросом мне удалось обновить оператор grep, чтобы получить желаемый результат, для всех, кто интересуется только решением bash, поэтому обновленная часть кода выглядит так:

for IPBL in `cat /tmp/IPs`; do 
  CT=`grep -c "^${IPBL%.[0-9]*.[0-9]*}\." /tmp/IPs`
    if [ "$CT" -gt "10" ]; then 
      echo "$IPBL  ${IPBL%.[0-9]*.[0-9]*}.0.0/16  $CT" >>/tmp/spam.lst
    fi
done
cat /tmp/spam.lst |sort -n

изменен аргумент формы grep
^-для начала с начала строки и
\.для добавления точки после второго числа в IP-адресе, что дает точное соответствие конкретному диапазону IP-адресов класса B:

"^${IPBL%.[0-9]*.[0-9]*}\."

И теперь ip 8.6.144.6 имеет только одно совпадение из файла IPs и, следовательно, не отображается в выводе, но одно совпадение класса B будет выглядеть так :
3.8.35.118  3.8.0.0/16  12
3.8.36.119  3.8.0.0/16  12
3.8.36.121  3.8.0.0/16  12
3.8.37.124  3.8.0.0/16  12
3.8.37.125  3.8.0.0/16  12
3.8.37.126  3.8.0.0/16  12
3.8.37.94  3.8.0.0/16  12
3.8.37.96  3.8.0.0/16  12
3.8.37.97  3.8.0.0/16  12
3.8.37.97  3.8.0.0/16  12
3.8.37.98  3.8.0.0/16  12
3.8.37.98  3.8.0.0/16  12
0
25.08.2021, 10:21

Теги

Похожие вопросы