我有一堆文件,每个文件看起来都是这样的:
HWI-ST913:300:C5W5DACXX:7:1101:1477:2147 Ha1_00044161 80.6 31 6 0 94 2 1 31 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1629:2128 Ha6_00047653 90.9 33 3 0 2 100 173 205 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1649:2180 Ha9_00011743 100.0 33 0 0 100 2 274 306 7.8e-12 65.9
HWI-ST913:300:C5W5DACXX:7:1101:1649:2180 Ha5_00006578 100.0 33 0 0 100 2 98 130 7.8e-12 65.9
HWI-ST913:300:C5W5DACXX:7:1101:1649:2180 Ha12_00033467 100.0 33 0 0 100 2 91 123 7.8e-12 65.9
HWI-ST913:300:C5W5DACXX:7:1101:6099:2062 B2KZF9_PICAB 100.0 33 0 0 1 99 73 105 2.4e-13 70.9
HWI-ST913:300:C5W5DACXX:7:1101:6891:2170 Ha2_00026275 87.9 33 4 0 2 100 27 59 9.3e-13 68.9
HWI-ST913:300:C5W5DACXX:7:1101:6891:2170 Ha13_00015465 87.9 33 4 0 2 100 884 916 9.3e-13 68.9
HWI-ST913:300:C5W5DACXX:7:1101:6891:2170 Ha17_00009154 87.9 33 4 0 2 100 420 452 9.3e-13 68.9
我只想保留第一列唯一的那些行。这是我想要的输出:
HWI-ST913:300:C5W5DACXX:7:1101:1477:2147 Ha1_00044161 80.6 31 6 0 94 2 1 31 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1629:2128 Ha6_00047653 90.9 33 3 0 2 100 173 205 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:6099:2062 B2KZF9_PICAB 100.0 33 0 0 1 99 73 105 2.4e-13 70.9
答案1
KISS 方法awk
:维护一个行数组和一个计数 - 然后仅打印末尾计数为 1 的行:
awk '{a[$1]=$0; c[$1]++} END{for (i in a) {if (c[i] == 1) print a[i]}}' file
uniq
或者,如果您有支持-w
( ) 选项的版本--check-chars
并且:
您的数据按第一个字段排序;并且
第一个字段的宽度是恒定的
那么你可以用它来代替:
uniq -uw 40 file
HWI-ST913:300:C5W5DACXX:7:1101:1477:2147 Ha1_00044161 80.6 31 6 0 94 2 1 31 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1629:2128 Ha6_00047653 90.9 33 3 0 2 100 173 205 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:6099:2062 B2KZF9_PICAB 100.0 33 0 0 1 99 73 105 2.4e-13 70.9
这样做的优点是保留原始文件的顺序 - 如果这对您的应用程序很重要。
答案2
一种方法可能就是这样。需要对同一文件进行双重解析,但结果按顺序打印:
$ awk 'NR==FNR{f1[$1]++;next}f1[$1]==1' file1 file1
HWI-ST913:300:C5W5DACXX:7:1101:1477:2147 Ha1_00044161 80.6 31 6 0 94 2 1 31 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1629:2128 Ha6_00047653 90.9 33 3 0 2 100 173 205 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:6099:2062 B2KZF9_PICAB 100.0 33 0 0 1 99 73 105 2.4e-13 70.9
答案3
仅考虑输入文件已排序,以下内容将适用于任何符合 POSIX 的系统:
sed 's/ .*//' file.txt | uniq -u | join - file.txt
如果原始文档中的空格分隔符实际上是制表符,则可以将sed
调用替换为cut -f1 file.txt
,并使其余部分保持不变。
答案4
仅扫描一次文件和按照与输入文件相同的顺序打印 uniq 行,使用:
在 GNU awk 中(使用“sorted_in”来确保数组的有序扫描):使用三个数组:
- 1 用于计算重复行数 (c[]),
- 一个用于行的排序顺序 (s[]) 和
- 一个用于它们自身的行 (v[])
最后,只打印计数为 1 的行。
awk 'BEGIN { PROCINFO["sorted_in"] = "@ind_num_asc" ; i=0}
!c[$1]++{s[++i]=$1;v[i]=$0}
END{for(i in v){if(c[s[i]]==1){print v[i]}}}' infile
请注意,将!c[$1]++
仅捕获第一个字段的第一次出现