텍스트 파일에서 겹치는 IP 범위 제거

텍스트 파일에서 겹치는 IP 범위 제거

내 연장을 위해이전 질문, 다음 형식의 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 범위를 제거하고 싶습니다.

예를 들어 위의 예에서는 첫 번째 행의 범위가 이미 세 번째 행에 포함되어 있으므로 삭제해야 합니다.

노트:IP 범위뿐만 아니라 전체 행(설명 포함)을 유지해야 합니다.

답변1

입력 줄 재정렬에 문제가 없다면 GNU Awk와 "sort" 명령을 사용하는 비교적 간단한 해결책이 있습니다. 기본 아이디어는 IP 주소를 포인트 쌍 대신 단일 숫자로 변환하여 비교를 매우 쉽게 만들고 -k특정 필드에서만 정렬하도록 지정할 수 있는 정렬 플래그를 사용하는 것입니다.

간결성을 위해 이는 공동 처리의 GNU awk 기능도 사용하므로 다음을 사용하기 전후에 데이터를 매우 쉽게 처리할 수 있습니다 sort.

편집하다:이 답변의 원래 버전에 있는 명령줄은 sort약간 잘못되었습니다. sort -k2,3r필드 합계는 실제로 단일 2키로 처리되어 3역순으로 정렬되었습니다. 먼저 필드별로 정렬 하고 (역방향) 필드를 순위결정자로 사용하여 sort -k2,2n -k3,3rn필요한 작업을 수행합니다 .23

# 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
    }
  }
}

관련 정보