比较同一文件中的多列

时间:2018-08-16 14:44:29

标签: bash awk

我想比较同一文件中的多列,以查看我在哪一行有差异,在这种情况下,前四列。该文件如下所示:

           Column1 Column2 Column3 Column4 Column5
              AA      AA      AA      AA    AA
              GG      GG      GG      GG    GG
              CC      GC      CC      CC    CC
              CC      TT      CC      GC    TT

如果我做了这样的事情:

 awk -F"\t" '{if ($1==$2) print $1, $2; else print NR}' file.txt 

我得到下一个输出:

             1
             AA      AA 
             GG      GG 
             4
             5

但是,如何用简单的语法同时比较前四列呢?我尝试过这样的事情:

       awk -F"\t" '{if ([$2,$3,$4]==$1) print $1, $2, $3, $4 ; else print NR}' File.txt

,但是它不起作用。

我的预期输出应该是:

              1 
              AA      AA      AA      AA
              GG      GG      GG      GG
              4
              5

我的文件有多于四列,所以我想比较列的组(在这种情况下,从列1到列4),并且如果这四个列具有相同的字符,则只打印这四个列;如果它们的行数相同,则只打印行数有差异。

我该如何实现?

3 个答案:

答案 0 :(得分:0)

我将使用循环逐步浏览您的专栏:

$ awk '{x=0;for(i=1;i<NF;i++){if($i!=$(i+1)){x=1}} print x?NR:$0}' input.txt

或者,为便于阅读:

{
  x=0                     # initialize the flag for each line
  for (i=1;i<NF;i++) {    # step through the fields
    if ($i!=$(i+1)) {     # test for a match with the next field
      x=1                 # and set a flag if we see different content.
    }
  }
  print x ? NR : $0       # print NR or the first field depending on flag value
}

此步骤逐步遍历所有字段(不仅仅是四个字段),将每个字段的内容与其后面的字段的内容进行比较。如果任何时候字段不匹配,则会设置一个标志。

最终语句中的三元运算符根据标志选择要显示的输出。

请注意,您期望的输出似乎从行首开始就修剪了空格。如果您确实需要这样做,可以在sub(/^[[:space:]]+/,"")语句之前print

答案 1 :(得分:0)

这可能是您想要的:

$ awk '{
    sub(/^[[:space:]]+/,"")
    delete uniq
    for (i=1;i<=4;i++) {
        uniq[$i]
        out=(i>1 ? out OFS : "") $i
    }
    print (length(uniq) > 1 ? NR : out)
}' file
1
AA AA AA AA
GG GG GG GG
4
5

这需要awk,它可以使用length(array)获取GNU awk可以使用的数组中元素的数量,我不确定其他元素。

假设您确实有一个支持length(array)的awk,那么仅当您在某些时候需要唯一值计数时(才这样做)还是使用a table of requirements比较相邻值才重要我的提供),而不是仅是一个/否(是否都提供1个或多个)。例如,如果您要打印每行中存在多少唯一值,则在打印行号后,这些值并不是唯一的:

awk '{
    sub(/^[[:space:]]+/,"")
    delete uniq
    for (i=1;i<=4;i++) {
        uniq[$i]
        out=(i>1 ? out OFS : "") $i
    }
    numUniq = length(uniq)
    print (numUniq > 1 ? NR OFS numUniq : out)
}' file
1 4
AA AA AA AA
GG GG GG GG
4 2
5 3

btw,如果您使用的awk不支持length(array),则可以编写自己的awk:

function alength(a, i,c) {for (i in a) ++c; return c+0}

,然后将其称为alength(array)

答案 2 :(得分:0)

如果使用关联数组,并在进行线性传递时增加每个值的计数。您可以简单地:

$ awk '{delete x; for(i=1;i<=NF;i++) x[$i]++; if (x[$NF]==NF) print $0; else print NR;}' file.txt
1
AA AA AA AA
GG GG GG GG
4
5