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

Например:

8.8.8.0/24
8.8.8.8
23.236.62.147
23.236.48.0/20
104.154.76.93
104.154.0.0/15
etc

Поэтому мне нужно удалить 23.236.62.147 (потому что это подсеть 23.236.48.0/20), 104.154.76.93 (потому что это подсеть 104.154.0.0/15), 8.8.8.8 (потому что это подсеть 8.8.8.0/24) и т.д.

Как это сделать в bash/command linux?

1 ответ1

0

С bash и GNU grep:

#!/bin/bash

common() {
  # From http://stackoverflow.com/a/35114656/3776858

  D2B=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
  declare -i c=0                              # set integer attribute

  # read and convert IPs to binary
  IFS=./ read -r a1 a2 a3 a4 m <<< "$1"
  b1="${D2B[$a1]}${D2B[$a2]}${D2B[$a3]}${D2B[$a4]}"

  IFS=./ read -r a1 a2 a3 a4 m <<< "$2"
  b2="${D2B[$a1]}${D2B[$a2]}${D2B[$a3]}${D2B[$a4]}"

  # find number of same bits ($c) in both IPs from left, use $c as counter
  for ((i=0;i<32;i++)); do
    [[ ${b1:$i:1} == ${b2:$i:1} ]] && c=c+1 || break
  done    

  # create string with zeros
  for ((i=$c;i<32;i++)); do
    fill="${fill}0"
  done    

  # append string with zeros to string with identical bits to fill 32 bit again
  new="${b1:0:$c}${fill}"

  # convert binary $new to decimal IP with netmask
  new="$((2#${new:0:8})).$((2#${new:8:8})).$((2#${new:16:8})).$((2#${new:24:8}))/$c"
  echo "$new"
}


cidr="$1"

# using process substitution
grep -vxFf <(
  grep -v / "$cidr" | while IFS= read -r ip1; do
    grep / "$cidr" | while IFS=/ read -r ip2 mask2; do
      out=$(common "$ip2/$mask2" "$ip1/32")
      out_mask="${out#*/}"
      if [[ $out_mask -ge $mask2 ]]; then   # -ge: greater-than-or-equal
        echo "$ip1"
      fi
    done
  done
) "$cidr" > cidr_clean.txt

Использование: ./shadow.sh your_cidr_file.txt

В вашем текущем каталоге вы получите cidr_clean.txt:

8.8.8.0/24
23.236.48.0/20
104.154.0.0/15

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .