Eu tenho 2 listas, uma contendo todos os endereços IP de 32 bits e a outra é uma lista de intervalos de IP e outros endereços IP. Preciso descobrir se cada IP da lista A existe em qualquer intervalo de IP ou endereço da lista B. O resultado final seria exibir os endereços da lista A que não existem na lista B. Isso seria fácil usando diff se o IP intervalos não estavam envolvidos. A lista em si contém quase 10.000 linhas, portanto, passar por isso manualmente levaria uma eternidade.
Responder1
Este script funciona no Linux/Bash. Não tenho certeza se está livre de bugs. Comente se quiser alguma explicação.
#!/bin/bash
# The script prints addresses from one file that are NOT
# in the ranges provided in another file.
# $1 is the file with addresses to check
# $2 is the file that holds the ranges
## in format x.x.x.x-y.y.y.y or as a single IP, one per line.
### Variables ###
inFile="$1"
rangesFile="$2"
typeset -a rangesLow rangesHigh #arrays of int
rangesCount=
### Functions ###
toInt () {
printf "%d\n" $(($1*256*256*256 + $2*256*256 + $3*256 + $4))
}
readRanges () {
while IFS=- read -a range
do
IFS=. read -a low <<< "${range[0]}"
[ -z "${range[1]}" ] && range[1]="${range[0]}"
IFS=. read -a high <<< "${range[1]}"
rangesLow+=( $(toInt "${low[@]}") )
rangesHigh+=( $(toInt "${high[@]}") )
done < "$rangesFile"
rangesCount=${#rangesLow[@]}
}
singleCheck () {
# $1 is the address to check.
# $2 and $3 are the bounds, low and high.
# Returns 0 if NOT in range.
[[ $1 -ge $2 ]] && [[ $1 -le $3 ]] && return 1
# To invert the logic of the script, instead of the line above
## use this one:
# [[ $1 -ge $2 ]] && [[ $1 -le $3 ]] || return 1
return 0
}
addressCheck () {
# The function takes in 4 octets of an IP as four positional parameters.
# Returns 1 if IP is in any range.
# If not in range, the address is printed to stdout.
local address
address=$(toInt "$@")
for ((i=0; i<rangesCount ; i++)) # Loop for all ranges.
do
singleCheck "$address" "${rangesLow[$i]}" "${rangesHigh[$i]}" || return 1
done
printf "%d.%d.%d.%d\n" "$@"
}
checkAll () {
while IFS=. read -a toCheck
do
addressCheck "${toCheck[@]}"
done < "$inFile"
}
main () {
readRanges
checkAll
}
### Execute ###
main
Baseado no pensamento brilhante de Hymie.
Responder2
Não conheço um script de shell, mas um programa deve ser capaz de converter ambas as listas de endereços IP quádruplos pontilhados em números inteiros únicos e, em seguida, comparar os números com o padrão maior que menor que.
i = (first octet * 256*256*256) + (second octet * 256*256)
+ (third octet * 256) + (fourth octet)