根据多列过滤行

时间:2013-10-23 09:02:18

标签: awk terminal compare multiple-columns

我想基于多列中的匹配来过滤行。 我有(各种)4列标签分隔文件。 我需要检查第1列中的所有重复出现,检查相应的第4列,如果值不同(即使只出现一次),则打印整行(4列)。

以下是输入的示例:

function-n  such_as-handheld-n  6.4623  A
function-n  such_as-hash-n  6.5328  A
party-n such_as-head-n  2.5586  A
function-n  such_as-headphone-n 8.0794  B
function-n  such_as-health-n    3.1938  A
party-n such_as-heartbeat-n 6.5902  B
party-n such_as-heat-n  3.9708  B
zebra-n at-1-aquatic-n  10.0476 B
zebra-n become-pelican-n    12.4166 B
zebra-n behind-idea-of-concept-n    16.0319 B
zebra-n move-lion-n 12.2017 B
zebra-n such_as-1-pole-n    8.9519  B
zebra-n try-reasoning-n 12.9504 B
zooplankton-n   than-1-mangrove-n   12.0638 B

因此结果如下:

function-n  such_as-handheld-n  6.4623  A
function-n  such_as-hash-n  6.5328  A
party-n such_as-head-n  2.5586  A
function-n  such_as-headphone-n 8.0794  B
function-n  such_as-health-n    3.1938  A
party-n such_as-heartbeat-n 6.5902  B
party-n such_as-heat-n  3.9708  B

as“function-n”和“party-n”是Column1中第4列中唯一具有不同值的值。

我看过这篇关于使用awk基于多列here丢弃行的帖子。 代码(由@Steve提出)如下:

FNR==NR {
    array[$0]++
    next
}

{
    counter = 0
    for (i in array) {
        split(i, holder, FS)
        if (holder[1] == $1) {
            counter++
        }
    }
    if (counter >= 2) {
        print
    }
}



$ awk -f script.awk file.txt{,}

除了2列数据外,此代码完全符合我的要求。 我试图修改脚本的一部分来比较第4列,如下所示:

{
    counter = 0
    for (i in array) {
        split(i, holder, FS)
        if (holder[1] == $4) {
            counter++
        }

然而,它不起作用。任何人都可以提供有关如何修改此脚本的见解,以便我可以获得所需的结果吗?

或许某人有更有效/优化的方法来处理这个问题? 谢谢。

2 个答案:

答案 0 :(得分:2)

我认为你必须非常努力地使用awk。在读完每一行之前,您无法开始打印,我认为您需要的数据结构有点超出了awk提供的范围。您可以使用更高级别的语言:Python,Perl,Ruby。

这是红宝石1.9.3:

ruby -F"\t" -ane '
    BEGIN { 
        f4 = Hash.new {|h,k| h[k] = Hash.new} 
        lines = Hash.new {|h,k| h[k] = Array.new} 
    }
    f4[$F[0]][$F[-1]] = 1
    lines[$F[0]] << [$., $_]
    END {
        output = []
        f4.each_pair do |key, subhash|
            if subhash.length > 1
                lines[key].each {|pair| output[pair[0]] = pair[1]}
            end
        end
        puts output
    }
'

的Perl:

perl -F"\t" -ane '
    $f4{$F[0]}{$F[-1]} = 1;
    push @{$lines{$F[0]}}, [$., $_];
    END {
        @output=();
        while (($key, $subhash) = each %f4) {
            if (keys(%$subhash) > 1) {
                $output[$_->[0]] = $_->[1] for @{$lines{$key}};
            }
        }
        print @output;
    }
'

答案 1 :(得分:0)

可能的解决方案(使用awk)如下:

$ awk'NR == FNR {if(A [$ 1]!= $ NF&amp;&amp; A [$ 1]){B [$ 1] ++} A [$ 1] = $ NF; next} {if (B [$ 1]){print}}'输入输入&gt;输出