Ich habe 2 Listen, eine mit allen 32-Bit-IP-Adressen und die andere ist eine Liste mit IP-Bereichen und anderen IP-Adressen. Ich muss herausfinden, ob jede IP in Liste A in einem IP-Bereich oder einer Adresse in Liste B vorhanden ist. Das Endergebnis wäre, die Adressen aus Liste A anzuzeigen, die in Liste B nicht vorhanden sind. Dies wäre mit diff einfach, wenn die IP-Bereiche nicht beteiligt wären. Die Liste selbst enthält fast 10.000 Zeilen, daher würde es ewig dauern, sie manuell durchzugehen.
Antwort1
Dieses Skript funktioniert unter Linux/Bash. Ich bin nicht sicher, ob es fehlerfrei ist. Wenn Sie eine Erklärung wünschen, schreiben Sie einen Kommentar.
#!/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
Basierend auf Hymies brillantem Gedanken.
Antwort2
Ich weiß nichts über ein Shell-Skript, aber ein Programm sollte in der Lage sein, beide Listen von IP-Adressen im Dotted-Quad-Format in einzelne Ganzzahlen umzuwandeln und die Zahlen dann mit dem Standardformat „Größer als, Kleiner als“ zu vergleichen.
i = (first octet * 256*256*256) + (second octet * 256*256)
+ (third octet * 256) + (fourth octet)