在文本文件中查找多行的公共元素

时间:2014-08-27 15:23:15

标签: awk text-processing

假设File.txt如下所示:

A1 B C D 
E F C H
C J 
A2 F B
D J C 
F T Y U I
B C N J Y

我需要检查以模式“^ A”开头的行,然后查找之后的元素(从$ 2到行尾)。然后我需要找到以这些元素开头的行中的公共元素。这是File.txt的输出:

A1 C J
A2 Y

A1 J C
A2 Y

输出中常见元素(例如J和C)的顺序无关紧要。

P.S。 Awk是首选。

2 个答案:

答案 0 :(得分:3)

将GNU awk用于真正的2D数组并删除数组和长度(数组):

$ cat tst.awk
{ for (i=1;i<=NF;i++) children[$1][$i] }
/^A/{ parents[$1]; delete children[$1][$1] }
END {
    for (parent in parents) {
        delete count
        printf "%s", parent
        for (child in children[parent])
            for (grandchild in children[child])
                if (++count[grandchild] == length(children[parent]))
                    printf " %s", grandchild
        print ""
    }
}

$ awk -f tst.awk file
A1 C J
A2 Y

只需检查非A行中任何字段出现次数的计数是否与A行中第2个+字段的计数相匹配,因为它表示在每种情况下都会出现。

答案 1 :(得分:1)

这有点难看,我觉得它应该以更干净的方式实现,但它至少可以处理样本数据。

/^A/ {
    amap[$1]=NF - 1
    for (i=2; i<=NF; i++) {
        rmap[$i]=rmap[$i] (rmap[$i]?SUBSEP:"") $1
    }
    next
}

$1 in rmap {
    split(rmap[$1], a, SUBSEP)
    for (f in a) {
        for (i=1; i<=NF; i++) {
            afmap[a[f],$i]++
        }
    }
}

END {
    for (af in afmap) {
        split(af, a, SUBSEP)
        if (afmap[af] == amap[a[1]]) {
            o[a[1]]=o[a[1]] (o[a[1]]?" ":"") a[2]
        }
    }
    for (f in o) {
        print f, o[f]
    }
}