탭으로 구분된 5개의 필드로 구성된 파일이 있습니다(이 경우 관련 없는 필드는 비어 있습니다).
1 2 URL email 5
https://www.a.com/t [email protected]
https://www.a.com [email protected]
https://www.b.fr [email protected]
https://www.b.fr/s/faq [email protected]
원하는 출력:
domain email(s)
a.com [email protected]
b.fr [email protected], [email protected]
속도:
- 열 3과 4를 분리합니다.
awk -F "\t" '{print $3 "\t\t" $4}'
그러면 위의 첫 번째 블록에 표시된 내용이 생성됩니다.
어떻게 진행하나요?
나는 필드를 grep하는 방법만 알고 있지만 필드를 분리하는 것은 원하는 출력 라인을 얻는 데 큰 도움이 되지 않습니다.
나는 이것에만 국한되지 않고 awk
, (플래그를 통해) 필드를 쉽게 분리할 수 있는 내가 아는 유일한 도구일 뿐입니다 -F
.
답변1
awk
GNU 사용 datamash
:
awk 'BEGIN{ OFS=FS="\t" }
NR>2{ # skip first two records
split($3, a, "/" ) # split $3 into array a on /
domain=a[3] # 3rd element is the domain name
sub(/^www\./, "", domain) # remove www. prefix
print domain, $4 # print domain and email
}
' file | datamash -g 1 unique 2
이 awk
섹션에서는 처음 두 줄을 건너뛰고 모든 기록에 대한 도메인과 이메일을 인쇄합니다. 이것은 ~이 될 것이다
a.com [email protected]
a.com [email protected]
b.fr [email protected]
b.fr [email protected]
그런 다음 출력은 datamash
첫 번째 필드로 파이프되어 입력을 그룹화하고 두 번째 필드에 대한 고유 값의 쉼표로 구분된 목록을 인쇄합니다.
산출:
a.com [email protected]
b.fr [email protected],[email protected]
제목 줄은 연습용으로 예약되어 있습니다.
답변2
GNU awk를 사용하여 배열의 배열 합계를 처리합니다 gensub()
.
$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR>1 { d2e[gensub(/[^.]+\.([^.]+\.[^./]+).*/,"\\1",1,$3)][$4] }
END {
print "domain", "emails(s)"
for (domain in d2e) {
cnt = 0
for (email in d2e[domain]) {
row = (cnt++ ? row ", " : domain OFS) email
}
print row
}
}
$ awk -f tst.awk file
domain emails(s)
a.com [email protected]
b.fr [email protected], [email protected]
답변3
사용밀러(sed의 도움으로):
$ mlr --prepipe 'sed "/^$/d"' --tsv put -q -S '
$domain = joinv(mapexcept(splitnvx(joinv(mapselect(splitnvx($URL,"/"),3),""),"."),1),".");
@e[$domain] = mapsum(@e[$domain],{$email:1});
end {
for(k,v in @e){@{email(s)}[k] = joink(v,",")};
emit @{email(s)}, "domain"
}' File.tsv
domain email(s)
a.com [email protected]
b.fr [email protected],[email protected]
sed --prepipe
명령은 입력이 TSV로 구문 분석될 수 있도록 불필요한 빈 줄을 제거합니다. 변수 $domain
는 URL
필드를 먼저 /
(세 번째 요소 선택) 분할한 다음 .
(첫 번째 요소를 제외한 모든 요소 선택, 예를 들어 www
) 두 번 분할하여 얻습니다. 그런 다음 스트림 외부 매핑은 다음 @e
과 같이 구성 됩니다.지도필드 수 email
– 동일한 도메인에서 중복된 이메일을 제거하는 단계입니다. 에서 end
이메일 맵을 쉼표로 구분된 문자열로 변환하고 내보냅니다.
답변4
이 문제는 세 번째 필드(실제로 그 일부)를 키로 사용하고 set
네 번째 필드가 포함된 해당 값을 사용하여 사전을 구성하면 해결될 수 있습니다. a의 유용성 set
은 요소를 본질적으로 고유하게 유지하므로 값을 고유하게 유지하기 위해 어떤 종류의 프로그래밍 연습에도 노력을 기울일 필요가 없다는 것입니다.
python3 -c 'import sys
ifile = sys.argv[1]
fs = ofs = "\t"
d = {}
with open(ifile) as fh:
for i,l in enumerate(fh,1):
if i < 3: continue
x,x,y,email,x = l.split(fs)
domain = y.split("/")[2].split(".",1)[1]
if domain in d:
d[domain].add(email)
else:
d[domain] = { email }
print(f"domain{ofs}email(s)",
*[k+ofs+", ".join(v) for k,v in d.items()],
sep="\n")
' file
domain email(s)
a.com [email protected]
b.fr [email protected], [email protected]