使用grep或awk删除具有相同字符串的整个列(带有标题)

时间:2015-01-22 03:12:36

标签: regex bash awk co

我有一个文件如下:

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这样做?非常感谢!

3 个答案:

答案 0 :(得分: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"

答案 1 :(得分: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值,则第一个1输出column1/3。否则输出0

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

相反,如果第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)

答案 2 :(得分: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