도메인 목록이 있습니다. 예는 다음과 같습니다.
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.com
및 media.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
입력 파일에서 편집 스크립트를 생성하는 데 사용됩니다. sed
이 sed
명령은 먼저 현재 줄의 모든 점을 이스케이프한 다음 수정된 줄을 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.ccc
aaa.bbb.ccc
\.bbb\.ccc$
그런 다음 이 스크립트는 두 번째 호출을 통해 원본 데이터에 적용되어 sed
표준 입력 스트림을 통해 편집 스크립트를 읽습니다.
초기 명령을 약간 수정하면 다음 sed
과 같이 이를 제거할 수 있습니다.grep
sed
$ 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에는 불변의 "부호"와 정규식 확장 기능( /x
Perl의 -옵션) 과 같은 멋진 기본값이 많이 있습니다 . 사용자 정의 문자 클래스는 <+[…]>
긍정 문자 클래스와 부정 문자 클래스 모두에 사용할 수 있습니다 <-[…]>
. Raku의 캡처는 처음부터 시작하는 $0
Perl과 달리 처음부터 시작됩니다 $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
답변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.org
fwikipedia.org
doms[]
두 번째 스크립트는 awk를 사용하여 각 도메인 이름을 역순으로 인쇄하므로 files.media.wikipedia.org
로 인쇄한 org.wikipedia.media.files
다음 전체 목록을 이 목록으로 연결하여 sort -u
중복 항목을 삭제하고(선택 사항) 결과적으로 더 짧은(즉, 상위) 도메인 이름이 즉시 표시됩니다. 하위 도메인을 앞에 인쇄하세요. 그런 다음 다음은 awk
현재 역방향 도메인 이름이 이전 도메인 이름 시작 부분의 하위 문자열인지 확인하는 것입니다. 이 문자열 자체는 하위 도메인이 아닙니다. 그렇다면 해당 도메인은 하위 도메인이므로 건너뛰고 그렇지 않은 경우 , 인쇄하고(원래 순서로 되돌리기) 비교할 다음 도메인의 새로운 기본 상위로 기억하십시오. 명확하지 않은 경우 각 명령을 개별적으로 실행하여 출력 내용을 확인하세요.