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 文本处理
75KB
1K SLoC
zet: 求文件并集、交集等
zet 是一个命令行工具,可以对被视为行集合的文件执行集合操作。例如,zet union x y z 输出出现在 x、y 或 z 中的行,zet intersect x y z 输出出现在所有这些文件中的行,以及 zet diff x y z 输出出现在 x 中但不出现在 y 或 z 中的行。 zet 只打印每行一次,并按照其在输入中首次出现顺序打印行。
以下是 zet 的子命令及其功能
zet union x y z输出出现在x、y或z中的行。zet intersect x y z输出出现在x、y和z中的行。zet diff x y z输出出现在x中但不出现在y或z中的行。zet single x y z输出在整个输入中恰好出现一次的行。zet single --file x y z输出在整个输入中恰好出现在x、y或z中的一个中的行。(输出将包括例如在y中出现两次但不在x或z中出现的行)zet multiple x y z输出在整个输入中出现多次的行。zet multiple --files x y z会输出出现在x、y和z中的两行或多行(但不会输出在y中出现但在x或z中未出现的行)。
使用 --count-lines 标志可以让 zet 显示输入中每行出现的次数。使用 --count-files 标志可以显示每行出现在多少个文件中。使用 -c 或 --count 标志类似于 --count-lines,除非设置了 --files,在这种情况下,它们的行为类似于 --count-files。使用 --count-none 标志可以关闭计数,并且可以用来覆盖其他计数标志。(在通常的 POSIX 规范中,最后给出的计数标志将覆盖任何之前的计数标志。)
示例
假设你在一个网站上维护三个邮件列表,该网站允许你下载会员名单作为 CSV 文件,并通过上传相同格式的 CSV 文件添加新成员。你有三个列表,分别是 a、b 和 c,人们已经加入,你想创建两个新的列表:一个是 everyone,其会员应该是加入过 a、b 和 c 中的任何一个人;另一个是 big-fans,其会员应该是加入过 a、b 和 c 三个列表的所有人。
你已经将会员名单 a、b 和 c 下载到 a.csv、b.csv 和 c.csv 中。要创建 everyone 和 big-fans 的会员名单,你可以使用 zet
$ zet union a.csv b.csv c.csv > everyone.csv
$ zet intersect a.csv b.csv c.csv > big-fans.csv
不幸的是,当你创建 everyone 和 big-fans 时,已经有新人加入了 a、b 和 c 列表。因此,你下载了这些列表的当前会员名单到 a-now.csv、b-now.csv 和 c-now.csv。你创建了 delta-everyone.csv 和 delta-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选项,与uniq和comm不同。对于大文件,zet比uniq快约4.5倍,比comm快10倍(见基准测试详情)。但是,zet比uniq或comm占用更多内存:zet将第一个文件参数读入内存,并且在(对于union、single和multiple)为不在第一个文件中的每一行分配额外的空间。相比之下,uniq和comm无论输入多大,都占用几乎固定的空间,因为它们依赖于输入(s)是排序的。因此,zet在遇到内存限制之前速度更快,此时它停止工作。
huniq命令比zet union略快,且占用更少内存,因为它只保留每行的哈希值而不是整个行。 (理论上,huniq可能会输出与另一条不同的行具有相同哈希值的行)。但是,zet union --count比huniq -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 intersect和zet diff)或其第一个输入和输出的大小中较大的一个(zet union、zet single和zet multiple)。
许可
根据以下任一许可授权:
- Apache License,版本2.0(LICENSE-APACHE或https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT或https://open-source.org.cn/licenses/MIT)
由您选择。
贡献
除非您明确说明,否则根据Apache-2.0许可证定义的,您有意提交以包含在本作品中的任何贡献,应按上述方式双重许可,不附加任何额外条款或条件。
依赖项
~9–19MB
~313K SLoC