#集合操作 #文件行 #并集 #第一行 #集合 #交集 #唯一

程序+库 zet

zet 查找被视为行集合的文件的并集、交集、集合差等

4 个版本 (1 个稳定版)

1.0.0 2023年4月18日
0.2.6 2023年2月2日
0.2.0 2021年7月4日
0.1.1 2021年6月15日

#523 in 文本处理

MIT/Apache

75KB
1K SLoC

zet: 求文件并集、交集等

zet 是一个命令行工具,可以对被视为行集合的文件执行集合操作。例如,zet union x y z 输出出现在 xyz 中的行,zet intersect x y z 输出出现在所有这些文件中的行,以及 zet diff x y z 输出出现在 x 中但不出现在 yz 中的行。 zet 只打印每行一次,并按照其在输入中首次出现顺序打印行。

Build status Crates.io

以下是 zet 的子命令及其功能

  • zet union x y z 输出出现在 xyz 中的行。
  • zet intersect x y z 输出出现在 xyz 中的行。
  • zet diff x y z 输出出现在 x 中但不出现在 yz 中的行。
  • zet single x y z 输出在整个输入中恰好出现一次的行。
  • zet single --file x y z 输出在整个输入中恰好出现在 xyz 中的一个中的行。(输出将包括例如在 y 中出现两次但不在 xz 中出现的行)
  • zet multiple x y z 输出在整个输入中出现多次的行。
  • zet multiple --files x y z 会输出出现在 xyz 中的两行或多行(但不会输出在 y 中出现但在 xz 中未出现的行)。

使用 --count-lines 标志可以让 zet 显示输入中每行出现的次数。使用 --count-files 标志可以显示每行出现在多少个文件中。使用 -c--count 标志类似于 --count-lines,除非设置了 --files,在这种情况下,它们的行为类似于 --count-files。使用 --count-none 标志可以关闭计数,并且可以用来覆盖其他计数标志。(在通常的 POSIX 规范中,最后给出的计数标志将覆盖任何之前的计数标志。)

示例

假设你在一个网站上维护三个邮件列表,该网站允许你下载会员名单作为 CSV 文件,并通过上传相同格式的 CSV 文件添加新成员。你有三个列表,分别是 abc,人们已经加入,你想创建两个新的列表:一个是 everyone,其会员应该是加入过 abc 中的任何一个人;另一个是 big-fans,其会员应该是加入过 abc 三个列表的所有人。

你已经将会员名单 abc 下载到 a.csvb.csvc.csv 中。要创建 everyonebig-fans 的会员名单,你可以使用 zet

$ zet union a.csv b.csv c.csv > everyone.csv
$ zet intersect a.csv b.csv c.csv > big-fans.csv

不幸的是,当你创建 everyonebig-fans 时,已经有新人加入了 abc 列表。因此,你下载了这些列表的当前会员名单到 a-now.csvb-now.csvc-now.csv。你创建了 delta-everyone.csvdelta-big-fans.csv,其中包含应添加到 everyone 列表和 big-fan 列表的会员记录。

$ zet union a-now.csv b-now.csv c-now.csv | zet diff - everyone.csv > delta-everyone.csv
$ zet intersect a-now.csv b-now.csv c-now.csv | zet diff - big-fans.csv > delta-big-fans.csv

与其他命令的比较

一些 zet 子命令与传统 Unix 命令类似

zet 传统
zet union uniq
zet intersect comm -12
zet diff comm -23
zet single uniq -u
zet multiple uniq -d

差异

  • zet 的输入不需要排序,并且它以输入中首次出现的顺序输出行。它可以接受多个输入文件(而不是只有一个(如 uniq)或两个(如 comm))。
  • zet没有-i-ignore-case选项,与uniqcomm不同。对于大文件,zetuniq快约4.5倍,比comm快10倍(见基准测试详情)。但是,zetuniqcomm占用更多内存:zet将第一个文件参数读入内存,并且在(对于unionsinglemultiple)为不在第一个文件中的每一行分配额外的空间。相比之下,uniqcomm无论输入多大,都占用几乎固定的空间,因为它们依赖于输入(s)是排序的。因此,zet在遇到内存限制之前速度更快,此时它停止工作。

huniq命令比zet union略快,且占用更少内存,因为它只保留每行的哈希值而不是整个行。 (理论上,huniq可能会输出与另一条不同的行具有相同哈希值的行)。但是,zet union --counthuniq -c略快,因为huniq -c会对其输入进行排序以计数。

注意

  • 如上所述,每行输出只出现一次,行以它们遇到的顺序输出。
  • 当命令行上没有给出文件路径时,zet从标准输入读取。
  • 当文件参数为-时,zet从标准输入而不是名为-的文件读取。(该文件可以作为./-传递给zet)
  • zet将UTF-16LE和UTF-16BE文件转换为UTF-8,并在比较行时忽略字节顺序标记(BOM)。如果它的第一个文件参数以BOM开头,zet仅在输出时在其前添加BOM。
  • zet在比较行时忽略所有行结束符(\r\n\n),因此,如果两条输入行的唯一区别是其中一条以\r\n结尾,而另一条以\r结尾,则这两条输入行相同。如果它的第一个文件参数的第一行以\r\n结尾,zet将\r\n作为每个输出行的结束,否则(如果第一行以\n结尾或第一文件只有一行且该行没有行终止符)以\n结尾。
  • zet将整个第一个输入文件读入内存。它的内存使用与其第一个输入的大小密切相关(zet intersectzet diff)或其第一个输入和输出的大小中较大的一个(zet unionzet singlezet multiple)。

许可

根据以下任一许可授权:

由您选择。

贡献

除非您明确说明,否则根据Apache-2.0许可证定义的,您有意提交以包含在本作品中的任何贡献,应按上述方式双重许可,不附加任何额外条款或条件。

依赖项

~9–19MB
~313K SLoC