根据开头字符相同的比例对几乎重复的行进行排序

根据开头字符相同的比例对几乎重复的行进行排序

是否有一个 *nix 工具/方法可以显示几乎重复的每两行(可能通过排序相邻),并按每行之间相同位置的相似字符数量进行排序?例如对于此列表:

alpha
Omega2
candy3
alpine
Omega23

它将显示:

Omega2
Omega23
alpha
alpine
candy3

因为alphaalpine共享相同的起始字符串alp。 并且和 的Omega2起始字符串也相同。 但是由于 'candy3' 没有配对(因为它与任何其他行都没有相似的开头),所以它显示在最后。 此外,一对行共享的起始字符越多,它们就会被放在越靠前的位置。Omega2Omega23

答案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 将出现在最终排序输出的顶部。

相关内容