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或http://opensource.org/licenses/MIT)
由您选择。
贡献
除非您明确说明,否则根据Apache-2.0许可证定义的,您有意提交以包含在本作品中的任何贡献,应按上述方式双重许可,不附加任何额外条款或条件。
依赖项
~9–19MB
~313K SLoC