如何按域对电子邮件进行分组,从目录中的所有文件中组合和汇总?

Jaf*_*son 3 command-line text-processing

我有一些 CSV 文件。每个文件都有一个电子邮件地址列表。以下是从文件中提取的数据:

%%%%%%%%%%@yahoo.com
%%%%%%@wanadoo.fr
%%%%raviplywoodglasscentre@yahoo.comravi
%%nameemail%%@yahoo.com
%.getincontact@numberland.com
%1%3@example.com
%1@example.com
Run Code Online (Sandbox Code Playgroud)

我试图尝试的是从这些电子邮件地址中提取域,然后以将与某个域关联的电子邮件一起列出的方式排列电子邮件地址。
例如:

yahoo.com,%%%%%%%%%%@yahoo.com
wanadoo.fr,%%%%%%@wanadoo.fr
yahoo.comravi,%%%%raviplywoodglasscentre@yahoo.comravi
yahoo.com,%%nameemail%%@yahoo.com
numberland.com,%.getincontact@numberland.com
example.com,%1%3@example.com
example.com,%1@example.com
Run Code Online (Sandbox Code Playgroud)

我试图获得的最终输出如下所示:

yahoo.com,%%%%%%%%%%@yahoo.com,%%nameemail%%@yahoo.com
wanadoo.fr,%%%%%%@wanadoo.fr
yahoo.comravi,%%%%raviplywoodglasscentre@yahoo.comravi
numberland.com,%.getincontact@numberland.com
example.com,%1%3@example.com,%1@example.com
Run Code Online (Sandbox Code Playgroud)

Jac*_*ijm 6

一种python方式,使用itertools' groupby()

1.在终端中为每个文件(目录中的所有文件)写入输出

注意终端显示的行数有限

#!/usr/bin/env python3
from operator import itemgetter
from itertools import groupby
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    lines = [[l.strip(), l.split("@")[-1].strip()] for l in \
             open(os.path.join(dr, f)).readlines()]
    lines.sort(key=itemgetter(1))
    for item, occurrence in groupby(lines, itemgetter(1)):
        func = [s[0] for s in list(occurrence)]; print(item+","+",".join(func))
Run Code Online (Sandbox Code Playgroud)

使用

  1. 将脚本复制到一个空文件中,另存为 group_domains.py
  2. 使用目标目录作为参数运行它:

    python3 /path/to/group_domains.py /directory/with/files
    
    Run Code Online (Sandbox Code Playgroud)

输出将类似于:

example.com,%1%3@example.com,%1@example.com
numberland.com,%.getincontact@numberland.com
wanadoo.fr,%%%%%%@wanadoo.fr
yahoo.com,%%%%%%%%%%@yahoo.com,%%nameemail%%@yahoo.com
yahoo.comravi,%%%%raviplywoodglasscentre@yahoo.comravi
Run Code Online (Sandbox Code Playgroud)

笔记

实际上,脚本在终端中为每个文件创建一个输出。我们可以轻松地组合(汇总)单独文件的输出,然后将分组结果写入文件等,但请提及。

解释

在理念上:

  1. 读取文件的行,并用“@”分割以读取域
  2. 创建的列表随后排序

    lines.sort(key=itemgetter(1))
    
    Run Code Online (Sandbox Code Playgroud)
  3. 并按域分组:

    groupby(lines, itemgetter(1))
    
    Run Code Online (Sandbox Code Playgroud)

结果(行)由项目(域)及其“成员”组成。

2. 将每个文件(同样是目录中所有文件)的报告写入重命名的文件中。

下面的脚本会将输出写入重命名的文件中,用法相同:

python3 /path/to/group_domains.py /directory/with/files
Run Code Online (Sandbox Code Playgroud)

从一个文件,如:

some_list.txt
Run Code Online (Sandbox Code Playgroud)

它将创建一个重命名的:

grouped_some_list.txt
Run Code Online (Sandbox Code Playgroud)

使用

简单地:

python3 /path/to/group_domains.py /directory/with/files
Run Code Online (Sandbox Code Playgroud)

3. 将整个目录的报告(摘要)写入单个文件

下面的版本将汇总目录中文件内的所有域。报告保存在文件中,设置为第二个参数。

example.com,%1%3@example.com,%1@example.com
numberland.com,%.getincontact@numberland.com
wanadoo.fr,%%%%%%@wanadoo.fr
yahoo.com,%%%%%%%%%%@yahoo.com,%%nameemail%%@yahoo.com
yahoo.comravi,%%%%raviplywoodglasscentre@yahoo.comravi
Run Code Online (Sandbox Code Playgroud)

使用

  1. 将脚本复制到一个 emty 文件中
  2. 运行:

    python3 /path/to/group_domains.py /directory/with/files /path/to/outputfile.txt
    
    Run Code Online (Sandbox Code Playgroud)

    (或任何扩展名)

笔记

最后一个版本将先总结每个文件,如在问题中提到,和另外的所有文件汇总为一个输出文件,其中来自单独的文件类似的结构域将被合并成每个域一行。


ste*_*ver 5

这是一个perl使用匿名数组散列的版本:

$ perl -F@ -alne '
    push @{ $h{$F[1]} }, $_ }{ 
    for $k (reverse sort keys %h) {print join ",", $k, @{ $h{$k} }
  }' emails.csv
yahoo.comravi,%%%%raviplywoodglasscentre@yahoo.comravi
yahoo.com,%%%%%%%%%%@yahoo.com,%%nameemail%%@yahoo.com
wanadoo.fr,%%%%%%@wanadoo.fr
numberland.com,%.getincontact@numberland.com
example.com,%1%3@example.com,%1@example.com
Run Code Online (Sandbox Code Playgroud)

订单不完全符合您的要求

  • @JafferWilson 你真的应该自己开始尝试这些事情。您似乎将此站点视为免费的脚本编写服务。在到目前为止您收到的几个答案中,您肯定已经开始学习如何编写自己的答案了。至少,您可以在 google 上搜索“迭代目录中的文件”或其他内容。 (2认同)