分享
三行代码  ›  专栏  ›  技术社区  ›  Apex

如何使用Bash删除csv文件中相同的列

  •  1
  • Apex  · 技术社区  · 1 周前

    像这样的问题已经有很多了,但都没有帮到我。我想保持简单:

    Class,Gene,col3,Class,Gene,col6,Class
    A,FF,23,A,FF,16,A
    B,GG,45,B,GG,808,B
    C,BB,43,C,BB,76,C
    

    我希望保持列的唯一性,这样所需的输出应该是:

    Class,Gene,col3,col6
    A,FF,23,16
    B,GG,45,808
    C,BB,43,76
    

    我用过 awk '!a[$0]++' 但它没有删除文件中重复的列。

    作为一个旁注:我有重复的列,因为我使用 paste 连接不同文件的命令 column-wise .

    2 回复  |  直到 1 周前
        1
  •  3
  •   anubhava    1 周前

    你可以用这个 awk 要根据第一行标题行中的名称打印唯一列,请执行以下操作:

    awk 'BEGIN {
       FS=OFS=","                        # set input/output field separators as comma
    }
    NR == 1 {                            # for first header row
       for (i=1; i<=NF; i++)             # loop through all columns
          if (!ucol[$i]++)               # if col name is not in a unique array
             hdr[i]                      # then store column no. in an array hdr
    }
    {
       for (i=1; i<=NF; i++)             # loop through all columns
          if (i in hdr)                  # if col no. is found in array hdr then print
            printf "%s",(i==1?"":OFS) $i # then print col with OFS
          print ""                       # print line break
    }' file
    
    Class,Gene,col3,col6
    A,FF,23,16
    B,GG,45,808
    C,BB,43,76
    
        2
  •  1
  •   Barmar    1 周前

    打印前两列,然后以3为步长迭代以跳过 Class Gene 行的其余部分中的列。

    awk -F, '{printf("%s,%s", $1, $2); for (i=3; i<=NF; i+=3) printf(",%s", $i); printf("\n")}' 
    
        3
  •  0
  •   Ed Morton    1 周前

    $ awk '
        BEGIN { FS=OFS="," }
        { r=$1 OFS $2; for (i=3; i<=NF; i+=3) r=r OFS $i; print r }
    ' file
    Class,Gene,col3,col6
    A,FF,23,16
    B,GG,45,808
    C,BB,43,76
    

    但在其他不那么简单的情况下:创建一个数组( f[] 它将输出字段号(根据第一行字段/列名称的唯一性确定)映射到输入字段号,然后只循环输出字段号(注意:您不必遍历所有输入字段,只需要遍历要输出的字段),打印相应输入字段号的值:

    $ cat tst.awk
    BEGIN { FS=OFS="," }
    NR==1 {
        for (i=1; i<=NF; i++) {
            if ( !seen[$i]++ ) {
                f[++nf] = i
            }
        }
    }
    {
        for (i=1; i<=nf; i++) {
            printf "%s%s", $(f[i]), (i<nf ? OFS : ORS)
        }
    }
    

    $ awk -f tst.awk file
    Class,Gene,col3,col6
    A,FF,23,16
    B,GG,45,808
    C,BB,43,76
    

    BEGIN { FS=OFS="," }
    NR==1 {
        numInFlds = NF
        for (inFldNr=1; inFldNr<=numInFlds; inFldNr++) {
            fldName = $inFldNr
            if ( !seen[fldName]++ ) {
                out2in[++numOutFlds] = inFldNr
            }
        }
    }
    {
        for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
            inFldNr = out2in[outFldNr]
            fldValue = $inFldNr
            printf "%s%s", fldValue, (outFldNr<numOutFlds ? OFS : ORS)
        }
    }