是否有一个 *nix 工具/方法可以显示几乎重复的每两行(可能通过排序相邻),并按每行之间相同位置的相似字符数量进行排序?例如对于此列表:
alpha
Omega2
candy3
alpine
Omega23
它将显示:
Omega2
Omega23
alpha
alpine
candy3
因为alpha
和alpine
共享相同的起始字符串alp
。 并且和 的Omega2
起始字符串也相同。 但是由于 'candy3' 没有配对(因为它与任何其他行都没有相似的开头),所以它显示在最后。 此外,一对行共享的起始字符越多,它们就会被放在越靠前的位置。Omega2
Omega23
答案1
我不知道有任何标准工具可以执行此特定任务。我们可以使用sort
+ awk
:对输入进行排序;将每个字符串与前一个字符串进行比较,计算它们的初始字符中有多少个相同;按该计数按降序对对进行排序。这是一个awk
程序:
BEGIN {OFS = "\t"}
# Collecting pairs, so these actions are skipped for the first line
NR > 1 {
for (i = 1; i <= len; i++)
if (substr($0,i,1) != substr(prev,i,1))
break
print --i, prev, $0 \
| "sort -k1rn,1 | cut -f2- | tr \\\\t \\\\n | awk \047!seen[$0]++\047"
# Above pipeline can be removed to output just `--i, prev, $0`
}
{
prev = $0
len = length
}
- 需要排序输入
- 假设输入字符串不包含
TAB
字符
如果输入文件每行一个字符串:
LC_COLLATE=C sort file | awk -f see_above.awk
输出:
Omega2
Omega23
alpha
alpine
candy3
注意:问题中提供的示例输入数据不足以进行测试(上面的输出恰好与相同LC_COLLATE=C sort file
)。为了理解正在做什么,这里是输出print --i, prev, $0
(在按数字排序、去编号和去重复之前):
6 Omega2 Omega23
0 Omega23 alpha
3 alpha alpine
0 alpine candy3
- 考虑将 alpha 和 alpine 更改为 aaaaalpha 和 aaaaalpine 时的输出:
6 Omega2 Omega23
0 Omega23 aaaaalpha
7 aaaaalpha aaaaalpine
0 aaaaalpine candy3
由于它们有 7 个相同的首字符,aaaaalpha 和 aaaaalpine 将出现在最终排序输出的顶部。