Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash awk中的Uniq;使用awk删除列中的重复值_Bash_Awk_Unique - Fatal编程技术网

Bash awk中的Uniq;使用awk删除列中的重复值

Bash awk中的Uniq;使用awk删除列中的重复值,bash,awk,unique,Bash,Awk,Unique,我有一个大数据文件,格式如下: ENST00000371026 WDR78,WDR78,WDR78, WD repeat domain 78 isoform 1,WD repeat domain 78 isoform 1,WD repeat domain 78 isoform 2, ENST00000371023 WDR32 WD repeat domain 32 isoform 2 ENST00000400908 RERE,KIAA0458, atrophin-1 like prote

我有一个大数据文件,格式如下:

ENST00000371026 WDR78,WDR78,WDR78,  WD repeat domain 78 isoform 1,WD repeat domain 78 isoform 1,WD repeat domain 78 isoform 2,
ENST00000371023 WDR32   WD repeat domain 32 isoform 2
ENST00000400908 RERE,KIAA0458,  atrophin-1 like protein isoform a,Homo sapiens mRNA for KIAA0458 protein, partial cds.,
这些列以制表符分隔。列中的多个值以逗号分隔。我想删除第二列中的重复值,以产生如下结果:

ENST00000371026 WDR78   WD repeat domain 78 isoform 1,WD repeat domain 78 isoform 1,WD repeat domain 78 isoform 2,
ENST00000371023 WDR32   WD repeat domain 32 isoform 2
ENST00000400908 RERE,KIAA0458   atrophin-1 like protein isoform a,Homo sapiens mRNA for KIAA0458 protein, partial cds.,
我尝试了下面的代码,但似乎没有删除重复的值

awk ' 
BEGIN { FS="\t" } ;
{
  split($2, valueArray,",");
  j=0;
  for (i in valueArray) 
  { 
    if (!( valueArray[i] in duplicateArray))
    {
      duplicateArray[j] = valueArray[i];
      j++;
    }
  };
  printf $1 "\t";
  for (j in duplicateArray) 
  {
    if (duplicateArray[j]) {
      printf duplicateArray[j] ",";
    }
  }
  printf "\t";
  print $3

}' knownGeneFromUCSC.txt

如何才能正确删除第2列中的重复项?

对不起,我知道您询问了awk。。。但是Perl使这变得简单得多:

$ perl -n -e ' @t = split(/\t/);
  %t2 = map { $_ => 1 } split(/,/,$t[1]);
  $t[1] = join(",",keys %t2);
  print join("\t",@t); ' knownGeneFromUCSC.txt

由于
NR==2
,脚本仅作用于文件中的第二条记录(行)。我把它拿了出来,但这可能是你想要的。如果是这样,你应该把它放回去

中的
操作符检查是否存在索引,而不是值,因此我创建了
duplicateArray
关联数组*,它使用
valueArray
中的值作为索引。这样就不必在循环中的循环中迭代两个数组

split
语句将“WDR78,WDR78,WDR78”视为四个字段,而不是三个字段,因此我添加了一个
if
,以防止打印空值,如果
if
不存在,则会打印“WDR78”

*实际上,AWK中的所有数组都是关联的

Pure Bash 4.0(一个关联数组):

declare-一部分#一行的一部分
声明-a第2部分#第2部分。柱
声明-用于记住第2部分中项目的检查
读行时;做
part=($line)#使用空格分隔行
如果s=','#分隔符为逗号
第二部分=(${part[1]})第二部分。使用逗号的列
如果[${第2部分[@]}-gt 1];然后#2个字段中有1个以上字段。专栏?
检查=()#空检查数组
new2=''#清空new2。柱
对于${part2[@]}中的项目;做
((勾选[$item]+)#记住2中的项目。柱
如果[${check[$item]}-eq 1];那么,还没看到吗?
new2=$new2,$item#添加到新2。柱
fi
完成
第[1]部分=${new2#,}#删除前导逗号
fi
IFS=$'\t'#输出的分隔符
回显“${part[*]}”#重建行
完成<“$infle”
Perl:

perl -F'\t' -lane'
  $F[1] = join ",", grep !$_{$_}++, split ",", $F[1]; 
  print join "\t", @F; %_ = ();
  ' infile  
awk:

awk-F'\t''{
n=拆分($2,t,“,”);_2=x
拆分(x,#如果支持,请使用删除

对于(i=0;++i+1)非常感谢您的回答。这个解决方案比我的好。但是我也很好奇为什么我的解决方案不起作用。出于这个原因,我会暂时保留设置一个可接受的答案。也许有人会知道如何在awk中执行此操作。
declare -a part                            # parts of a line
declare -a part2                           # parts 2. column
declare -A check                           # used to remember items in part2

while read  line ; do
  part=( $line )                           # split line using whitespaces
  IFS=','                                  # separator is comma
  part2=( ${part[1]} )                     # split 2. column using comma
  if [ ${#part2[@]} -gt 1 ] ; then         # more than 1 field in 2. column?
    check=()                               # empty check array
    new2=''                                # empty new 2. column
    for item in ${part2[@]} ; do 
      (( check[$item]++ ))                 # remember items in 2. column
      if [ ${check[$item]} -eq 1 ] ; then  # not yet seen?
        new2=$new2,$item                   # add to new 2. column
      fi 
    done
    part[1]=${new2#,}                      # remove leading comma
  fi 
  IFS=$'\t'                                # separator for the output
  echo "${part[*]}"                        # rebuild line
done < "$infile"
perl -F'\t' -lane'
  $F[1] = join ",", grep !$_{$_}++, split ",", $F[1]; 
  print join "\t", @F; %_ = ();
  ' infile  
awk -F'\t' '{
  n = split($2, t, ","); _2 = x
  split(x, _) # use delete _ if supported
  for (i = 0; ++i <= n;)
    _[t[i]]++ || _2 = _2 ? _2 "," t[i] : t[i]
  $2 = _2 
  }-3' OFS='\t' infile