タブで区切られた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
セクションでは、最初の2行をスキップし、すべての履歴のドメインと電子メールを印刷します。これは〜になります
a.com [email protected]
a.com [email protected]
b.fr [email protected]
b.fr [email protected]
その後、出力はdatamash
最初のフィールドにパイプされ、入力をグループ化し、2番目のフィールドの固有値のカンマ区切りリストを印刷します。
出力:
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
フィールドを最初に/
(3番目の要素を選択)分割し、次に.
(最初の要素を除くすべての要素を選択する、たとえばwww
)2回分割することによって取得されます。その後、ストリーム外部マッピングは次@e
のように構成されます。地図フィールド数email
- 同じドメインから重複した電子メールを削除する手順。でend
メールマップをコンマ区切り文字列に変換してエクスポートします。
答え4
この問題は、3番目のフィールド(実際にはその一部)をキーとして使用し、4set
番目のフィールドを含む対応する値を使用して辞書を設定することで解決できます。 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]