0

我有一个文件如下:

name1   name2   name3   name4    
AA  BB  BB  CC   
AA  AA  BB  CC   
AA  CC  BB  CC   
AA  DD  BB  DD   
AA  DD  BB  AA   

第 1 列和第 3 列本身具有相同的字符串。如果情况如上所述,我希望删除整个列,但保留标题。所以最终文件会变成这样。

name2   name4   
BB  CC         
AA  CC   
CC  CC   
DD  DD   
DD  AA   

有没有办法使用 grep 或 awk 来做到这一点?非常感谢!

4

3 回答 3

1

这在性能方面并不是完全最优的,但它确实使用awk并且它确实适用于您的样本输入:

file=$1

header=$(head -1 "$file")
i=1
goodcols=""
for colname in $header; do
  count=$(awk "NR>1 {print \$$i}" "$file" | sort -u | wc -l)
  if [ $count -gt 1 ]; then
    if [ -z "$goodcols" ]; then
      goodcols="\$$i"
    else
      goodcols="$goodcols, \$$i"
    fi
  fi
  i=$((i+1))
done

awk "{print $goodcols}" "$file"
于 2015-01-22T03:35:16.920 回答
0

UNIX shell 只是一个调用 UNIX 工具的环境。用于一般文本操作的 UNIX 工具是 awk,所以只需使用它:

$ cat tst.awk
{
    for (col=1; col<=NF; col++) {
        val[NR,col] = $col
        if ( (NR>1) && (!seen[col,$col]++) ) {
            cnt[col]++
        }
    }
}
END {
    for (row=1; row<=NR; row++) {
        ofs = ""
        for (col=1; col<=NF; col++) {
            if (cnt[col] != 1) {
                printf "%s%s", ofs, val[row,col]
                ofs = OFS
            }
        }
        print ""
    }
}

$ awk -f tst.awk file
name2 name4
BB CC
AA CC
CC CC
DD DD
DD AA
于 2015-01-22T04:02:49.307 回答
0

如果您的意图是打印整个文件,如果任何行的第 1 列和第 3 列值不同,并且仅打印第 2 列和第 4 列,其中行在第 1 列和第 3 列中具有相同的值,则以下脚本将执行此操作:

same=$(awk 'BEGIN{same=1}NR==1{next}$1!=$3{same=0;exit}{}END{print same}' qq.in)
if [[ $same -eq 1 ]] ; then
    awk '{print $2" "$4}' qq.in
else
    cat qq.in
fi

如果所有行(当然标题除外)都具有相同的值,则第一个awk输出。否则输出.1column1/30

然后,您只需使用它来过滤列,或按原样输出文件。

相反,如果您只想在第 1 列中的所有值都相同且第 3 列中的所有值相同(根据您的测试数据)的情况下删除第 1 列和第 3 列,请将第一行更改为:

allsame=$(awk 'BEGIN{allsame=1}NR==1{next}NR==2{val1=$1;val3=$3;next}$1!=val1||$3!=val3{allsame=0;exit}{}END{print allsame}' qq.in)
于 2015-01-22T03:56:09.657 回答