2010-06-04 79 views
4

列刪除重複值I有一個大的數據文件在下面的格式如下:awk中的Uniq;在使用AWK

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列中的重複項?

回答

6

你的腳本僅作用於因NR==2文件中的第二個記錄(行)。我拿出來了,但可能是你打算的。如果是這樣,你應該把它放回去。

in的操作者檢查用於索引,不是值的存在,所以我做duplicateArray關聯數組*valueArray作爲其指標使用的值。這樣可以避免在循環內的循環中迭代兩個數組。

split語句看到「WDR78,WDR78,WDR78,」四場,而不是三個,所以我說的if保持它打印一個空值,這將導致「 WDR78,」正在打印如果if間沒有在那裏。

*在現實中AWK所有陣列是相關聯的。

awk ' 
BEGIN { FS="\t" } ; 
{ 
    split($2, valueArray,","); 
    j=0; 
    for (i in valueArray) 
    { 
    if (!(valueArray[i] in duplicateArray)) 
    { 
     duplicateArray[valueArray[i]] = 1 
    } 
    }; 
    printf $1 "\t"; 
    for (j in duplicateArray) 
    { 
    if (j) # prevents printing an extra comma 
    { 
     printf j ","; 
    } 
    } 
    printf "\t"; 
    print $3 
    delete duplicateArray # for non-gawk, use split("", duplicateArray) 
}' 
3

對不起,我知道你問的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 
+0

+1非常感謝您的答覆。這個解決方案比我的要好。不過,我也很好奇爲什麼我的解決方案無法正常工作。出於這個原因,我會暫時設定一個被接受的答案。也許有人會知道如何在awk中做到這一點。 – 2010-06-05 00:07:39

2

純擊4.0(一種締陣列):

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" 
3

的Perl:

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

AWK:

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 

在AWK腳本中的第4行是用於保存原始的訂單o f在過濾唯一值後,在第二個字段中的值。