하위 도메인 또는 기존 도메인 삭제

하위 도메인 또는 기존 도메인 삭제

도메인 목록이 있습니다. 예는 다음과 같습니다.

account.google.com
drive.google.com
google.com
bgoogle.com
yahoo.co.uk
stats.wikipedia.org
media.wikipedia.org
files.media.wikipedia.org
bible.com

기존 도메인의 하위 도메인을 모두 삭제하고 싶습니다. 예를 들어 위 목록의 경우 google.commedia.wikipedia.org하위 도메인이 있으므로 해당 하위 도메인을 제거해야 합니다.

따라서 위 목록의 결과는 다음과 같습니다.

google.com
bgoogle.com
yahoo.co.uk
stats.wikipedia.org
media.wikipedia.org
bible.com

Python으로 일부 코드를 작성해 보았지만 완료하는 데 시간이 오래 걸립니다. 이 작업을 가장 빠르게 수행하려면 어떻게 해야 합니까?

답변1

.귀하의 질문은 "따라가지 않는 가장 긴 a만 유지하고 줄 끝까지는 .아무것도 유지하지 마십시오 . 이를 고유하게 만드십시오" 로 다시 공식화할 수 있는 것처럼 들립니다 . .그렇다면 다음을 수행할 수 있습니다.

$ awk -F"." -v OFS="." '{print $(NF-1),$(NF)}' file | sort -u
bgoogle.com
bible.com
google.com
wikipedia.org

또는 모든 작업을 수행하려면 다음을 수행하십시오 awk.

$ awk -F"." '{ k[$(NF-1)"."$(NF)]++}END{for (i in k){print i}}' file 
bgoogle.com
bible.com
wikipedia.org
google.com

또는 GNU grep:

$ grep -oP '[^.]+\.[^.]+$' file  | sort -u
bgoogle.com
bible.com
google.com
wikipedia.org

또는 Perl 및 GNU 정렬

$ perl -pe 's/.*?([^.]+\.[^.]+$)/$1/' file | sort -u
bgoogle.com
bible.com
google.com
wikipedia.org

아니면 그냥 펄

$ perl -ne '$k{$1}++ for s/.*?([^.]+\.[^.]+$)/$1/; END{ print keys(%k) }' file 
bible.com
bgoogle.com
wikipedia.org
google.com

아니면 그냥 펄

$ perl -ne 's/.*?([^.]+\.[^.]+)$/$1/; next if ++$k{$1}>1; print' file 
google.com
bgoogle.com
wikipedia.org
bible.com

아니면 sed 및 정렬

$ sed -E 's/.*\.([^.]+\.[^.]+)$/\1/' file | sort -u
bgoogle.com
bible.com
google.com
wikipedia.org

답변2

$ sed -e 's/\./\\./g' -e 's,.*,/\\.&$/d,' file | sed -f /dev/stdin file
google.com
bgoogle.com
yahoo.co.uk
stats.wikipedia.org
media.wikipedia.org
bible.com

이는 먼저 sed입력 파일에서 편집 스크립트를 생성하는 데 사용됩니다. sedsed명령은 먼저 현재 줄의 모든 점을 이스케이프한 다음 수정된 줄을 d특정 정규식 트리거를 사용하는 명령으로 변환합니다.

질문에 제공된 파일의 경우 편집 스크립트는 다음과 같습니다.

/\.account\.google\.com$/d
/\.drive\.google\.com$/d
/\.google\.com$/d
/\.bgoogle\.com$/d
/\.yahoo\.co\.uk$/d
/\.stats\.wikipedia\.org$/d
/\.media\.wikipedia\.org$/d
/\.files\.media\.wikipedia\.org$/d
/\.bible\.com$/d

.이 스크립트는 로 끝나는 호스트 이름과 그 뒤에 원본 데이터의 호스트 이름이 포함된 입력 줄을 모두 제거합니다 . 예를 들어 aaa.bbb.ccc정규식과 일치하므로 데이터에서 if가 제거됩니다 .bbb.cccaaa.bbb.ccc\.bbb\.ccc$

그런 다음 이 스크립트는 두 번째 호출을 통해 원본 데이터에 적용되어 sed표준 입력 스트림을 통해 편집 스크립트를 읽습니다.


초기 명령을 약간 수정하면 다음 sed과 같이 이를 제거할 수 있습니다.grepsed

$ sed -e 's/\./\\./g' -e 's/.*/\\.&$/' file | grep -v -f /dev/stdin file
google.com
bgoogle.com
yahoo.co.uk
stats.wikipedia.org
media.wikipedia.org
bible.com

grep이는 읽기를 위한 정규식의 기본 세트를 생성합니다 -f.

\.account\.google\.com$
\.drive\.google\.com$
\.google\.com$
\.bgoogle\.com$
\.yahoo\.co\.uk$
\.stats\.wikipedia\.org$
\.media\.wikipedia\.org$
\.files\.media\.wikipedia\.org$
\.bible\.com$

이 유틸리티는 입력에서 일치하는 행을 제거하는 grep데 사용됩니다 .-v

답변3

사용행복하다(이전 Perl_6)

...@terdon에 의해 번역됨 우수한 Perl 솔루션:

~$ raku -ne 'BEGIN my %k; %k{$0}++ for s/ .*? (<-[.]>+ \. <-[.]>+ $)/$0/; END .key.put for %k;'  file

#OR:

~$ raku -ne 'BEGIN my %k; s/ .*? (<-[.]>+ \. <-[.]>+ $) /$0/; next if ++%k{$0} > 1; .put;'  file

다음은 Perl 프로그래밍 언어 계열인 Raku로 작성된 솔루션입니다. Raku에는 불변의 "부호"와 정규식 확장 기능( /xPerl의 -옵션) 과 같은 멋진 기본값이 많이 있습니다 . 사용자 정의 문자 클래스는 <+[…]>긍정 문자 클래스와 부정 문자 클래스 모두에 사용할 수 있습니다 <-[…]>. Raku의 캡처는 처음부터 시작하는 $0Perl과 달리 처음부터 시작됩니다 $1.

입력 예:

account.google.com
drive.google.com
google.com
bgoogle.com
stats.wikipedia.org
media.wikipedia.org
files.media.wikipedia.org
bible.com

예제 출력:

google.com
bgoogle.com
wikipedia.org
bible.com

https://raku.org

답변4

이것은 아마도 awk로 하고 싶은 일일 것입니다:

$ cat tst.sh
#!/usr/bin/env bash

awk '
    { doms[$0] }
    END {
        for ( dom in doms ) {
            n = gsub(/[.]/,"&",dom)
            parent = dom
            foundParent = 0
            for ( i=1; i<n; i++ ) {
                sub(/[^.]+\./,"",parent)
                if ( parent in doms ) {
                    foundParent = 1
                    break
                }
            }
            if ( !foundParent ) {
                print dom
            }
        }
    }
' "${@:--}"

$ ./tst.sh file
media.wikipedia.org
bgoogle.com
bible.com
google.com
stats.wikipedia.org

또는 전체 파일을 awk의 메모리에 저장하고 싶지 않은 경우:

$ cat tst.sh
#!/usr/bin/env bash

awk '
    BEGIN { FS=OFS="." }
    {
        for ( i=NF; i>=1; i-- ) {
            printf "%s%s", $i, (i>1 ? OFS : ORS)
        }
    }
' "${@:--}" |
sort -u |
awk '
    BEGIN { FS=OFS="." }
    index($0,base".") != 1 {
        base = $0
        for ( i=NF; i>=1; i-- ) {
            printf "%s%s", $i, (i>1 ? OFS : ORS)
        }
    }

'

$ ./tst.sh file
bgoogle.com
bible.com
google.com
media.wikipedia.org
stats.wikipedia.org

위의 첫 번째 스크립트는 모든 필드를 배열의 메모리로 읽은 doms[]다음 이를 반복하여 "." 사이의 선행 문자열을 2개만 남은 위치까지 제거하고(따라서 및 가 files.media.wikipedia.org됨 ), 또한 상위 문자열이에도 존재하는지 확인합니다. 배열이 그렇다면 현재 도메인이 입력에도 존재하는 상위 도메인의 하위임을 알기 때문에 인쇄하지 않습니다.media.wikipedia.orgfwikipedia.orgdoms[]

두 번째 스크립트는 awk를 사용하여 각 도메인 이름을 역순으로 인쇄하므로 files.media.wikipedia.org로 인쇄한 org.wikipedia.media.files다음 전체 목록을 이 목록으로 연결하여 sort -u중복 항목을 삭제하고(선택 사항) 결과적으로 더 짧은(즉, 상위) 도메인 이름이 즉시 표시됩니다. 하위 도메인을 앞에 인쇄하세요. 그런 다음 다음은 awk현재 역방향 도메인 이름이 이전 도메인 이름 시작 부분의 하위 문자열인지 확인하는 것입니다. 이 문자열 자체는 하위 도메인이 아닙니다. 그렇다면 해당 도메인은 하위 도메인이므로 건너뛰고 그렇지 않은 경우 , 인쇄하고(원래 순서로 되돌리기) 비교할 다음 도메인의 새로운 기본 상위로 기억하십시오. 명확하지 않은 경우 각 명령을 개별적으로 실행하여 출력 내용을 확인하세요.

관련 정보