我正在写一些处理文件匹配的东西,我需要一个反转操作。我有一个文件列表(例如来自find . -type f -print0 | sort -z >lst
)和一个匹配列表(例如来自grep -z foo lst >matches
– 请注意,这只是一个示例;matches
可以是任何任意子集(包括空或完整)或lst
),现在我想反转此列表。
背景:我正在实施类似的事情查找(1)例外文件列表(尽管文件在调用时确实存在于文件系统中,但该列表可能已被预先过滤)。如果文件列表不是那么大,我可以使用find "${files[@]}" -maxdepth 0 -somecondition -print0
,但即使适度使用我正在编写的内容也会超出 Linux 或 BSDargv
大小限制。
如果行不是用 NUL 分隔的,我可以使用comm -23 lst matches >inverted
.如果匹配不是用 NUL 分隔的,我可以使用grep -Fvxzf matches lst
.但是,从我在第一段中提到的生成器来看,两者都是。
假设安装了 GNU 工具,所以这不需要在 Debian 之外进行移植,因为我正在使用find -print0
和sort -z
朋友已经(虽然一些 BSD 有它,所以如果它可以在“更便携”中完成,我不会抱怨) 。
我正在尝试在这里进行代码重用;另外,comm -23
基本上已经是完美的工具了,除了它不支持更改输入行分隔符(尚),并且通讯无论如何,它是一个被低估且不够知名的工具。如果 Unix/Linux 工具箱没有提供任何明智的东西,我可能会comm -23
在 shell 中重新实现一种形式(简化为这一个用例),因为脚本已经(出于其他原因)需要一个碰巧支持的 shellread -d ''
对于 NUL 分隔的输入,但这会很慢(而且费力……我在工作日结束时发布了此内容,希望有人知道我明天或 28 日何时拿起它)。
答案1
如果您comm
支持非文本输入(就像 GNU 工具通常所做的那样),您可以随时交换 NUL 和 nl (这里使用支持进程替换的 shell(顺便说一句,您在 mksh 中有任何计划吗?)):
comm -23 <(tr '\0\n' '\n\0' < file1) <(tr '\0\n' '\n\0' < file2) |
tr '\0\n' '\n\0'
那是一个常用技术。
答案2
如果您使用 grep 来搜索匹配项,则可以使用-v
grep 选项来查找不匹配的行。