リスト A の IP アドレスがリスト B の IP 範囲のリスト内に存在するかどうかを識別する

リスト A の IP アドレスがリスト B の IP 範囲のリスト内に存在するかどうかを識別する

リストが 2 つあります。1 つはすべての 32 ビット IP アドレスを含み、もう 1 つは IP 範囲とその他の IP アドレスを含むリストです。リスト A 内の各 IP がリスト B 内のいずれかの IP 範囲またはアドレスに存在するかどうかを調べる必要があります。最終結果は、リスト B に存在しないリスト A のアドレスを表示することです。IP 範囲が関係していなければ、これは diff を使用して簡単に実行できます。リスト自体には約 10,000 行が含まれているため、これを手動で調べるには永遠に時間がかかります。

答え1

このスクリプトは Linux/Bash ではうまく機能します。バグがないかどうかはわかりません。説明が必要な場合はコメントしてください。

#!/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

hymie の素晴らしい考えに基づいています。

答え2

シェル スクリプトについてはわかりませんが、プログラムは両方のリストをドットで区切られた 4 つの IP アドレスから単一の整数に変換し、標準の大なり小なりを使用して数値を比較できるはずです。

i = (first octet * 256*256*256) + (second octet * 256*256)
  + (third octet * 256) + (fourth octet)

関連情報