私の延長のために前の質問、次の形式のIP範囲のリストがあります。
Long description:20.1.1.0-20.1.1.14
Another description:5.5.5.0-5.5.5.100
Yet another description:20.1.1.0-20.1.1.40
重複したエントリはありませんが、重複するIP範囲を削除したいと思います。
たとえば、上記の例では、最初の行の範囲がすでに3番目の行に含まれているため、削除する必要があります。
メモ:IP範囲だけでなく、行全体(説明を含む)も維持する必要があります。
答え1
入力行の並べ替えに問題がない場合は、GNU Awkと「sort」コマンドを使用する比較的簡単な解決策があります。デフォルトのアイデアは、IPアドレスをポイントペアではなく単一の数値に変換して比較を非常に簡単にし、特定のフィールド-k
でのみソートするように指定できるソートフラグを使用することです。
簡潔にするために、これは共同処理のGNU awk機能も使用するため、以下を使用する前後にデータを非常に簡単に処理できますsort
。
編集する:この回答の元のバージョンのコマンドラインはsort
少し間違っていました。sort -k2,3r
フィールドの合計は実際には単一の2
キーとして処理され、逆の順序3
でソートされました。まず、フィールドごとにソートし、(逆方向)フィールドをランク付け子として使用してsort -k2,2n -k3,3rn
必要な操作を実行します。2
3
# Run as: gawk -F: -f <thisfile.awk> <input file>
BEGIN {
# Define the sort command that we will be using later as a variable
# Sort by
# - the 1st ip, smallest-to-largest
# - the 2nd ip, largest-to-smallest
sort="sort -n -t: -k2,2n -k3,3nr";
}
# For every line:
{
# Store the individual components of the addresses into 'ips'
match($2, /([[:digit:]]+).([[:digit:]]+).([[:digit:]]+).([[:digit:]]+)\
-([[:digit:]]+).([[:digit:]]+).([[:digit:]]+).([[:digit:]]+)/, ips);
# Add the components together to get the IPs as a single number.
# The print also uses : as the delimiter between the 2 IPS for simplicity
print $1":"ips[4]+256*(ips[3]+256*(ips[2]+256*ips[1])) \
":"ips[8]+256*(ips[7]+256*(ips[6]+256*ips[5])) \
|& sort
}
# After sending all lines to sort in the appropriate format
END {
# Close sort's input stream, so that we can read its output
close(sort, "to");
# Keep track of the upper end of the previous range
prevHigh=0;
# Read & field-split all lines from sort's output
while((sort |& getline) > 0) {
# One range is contained in another if its low address is >= the
# other's (guaranteed by the sort command) and its high address is <=
# the other's. So, we should print this record when its high address is >
# prevHigh:
if ($3 > prevHigh) {
print $1":"int($2/(256*256*256))%256"."int($2/(256*256))%256"." \
int($2/256)%256"."$2%256 \
"-"int($3/(256*256*256))%256"."int($3/(256*256))%256"." \
int($3/256)%256"."$3%256 \
# This is now the previous range
prevHigh = $3
}
}
}