我有一个制表符分隔的列文本,如下所示
A B1 B1 C1
B B2 D2
C C12 C13 C13
D D3 D5 D9
G F2 F2
我怎样才能像下面这样转换上表
A B1 C1
B B2 D2
C C12 C13
D D3 D5 D9
G F2
我已经提取了我的真实数据文件,它是一个制表符分隔的文件,我已经尝试了您(Stéphane Chazelas?)发布的命令行,它工作正常,但无法删除最后一列上的重复项
A CD274 PDCD1LG2 CD276 PDCD1LG2 CD274
B NEK2 NEK6 NEK10 NEK10 NEKL-4
C TNFAIP3 OTUD7B OTUD7B TNFAIP3 TNFAIP3
D DUSP16 DUSP4 DUSP8 VHP-1 DUSP8
E AGO2 AGO2 AGO2 AGO2 AGO2
输出需要如下
A CD274 CD276 PDCD1LG2
B NEK2 NEK6 NEK10 NEKL-4
C TNFAIP3 OTUD7B
D DUSP16 DUSP4 DUSP8 VHP-1
E AGO2
答案1
第一组示例数据:
$ awk -vOFS='\t' '{ r=""; delete t; for (i=1;i<=NF;++i) { if (!t[$i]++) { r = r ? r OFS $i : $i } } print r }' file
A B1 C1
B B2 D2
C C12 C13
D D3 D5 D9
G F2
第二组示例数据(相同的awk
脚本):
$ awk -vOFS='\t' '{ r=""; delete t; for (i=1;i<=NF;++i) { if (!t[$i]++) { r = r ? r OFS $i : $i } } print r }' file
A CD274 PDCD1LG2 CD276
B NEK2 NEK6 NEK10 NEKL-4
C TNFAIP3 OTUD7B
D DUSP16 DUSP4 DUSP8 VHP-1
E AGO2
该脚本逐行读取输入文件file
,并且对于每一行,它都会遍历每个字段,构建输出行r
.如果字段中的值已添加到输出行(由t
已用字段值的查找表 确定),则该字段将被忽略,否则将被添加。
当输入行的所有字段都已处理完毕后,将输出构造的行。
-vOFS='\t'
输出字段分隔符在命令行上设置为制表符。
剧本awk
揭晓:
{
r = ""
delete t
for (i = 1; i <= NF; ++i) {
if (!t[$i]++) {
r = r ? r OFS $i : $i
}
}
print r
}
答案2
sed/tr、uniq 和 Paste
while read -r l; do sed 's/\t/\n/g' <<< "$l" | uniq | paste -s; done < test
或 POSIX 兼容:
while read -r l; do echo "$l" | tr '\t' '\n' | uniq | paste -s -; done < test
对于文件,test
这将逐行用Tab换行符替换所有字符,运行以删除重复项并再次uniq
用字符替换换行符。Tab
$ cat test
A B1 B1 C1
B B2 D2
C C12 C13 C13
D D3 D5 D9
G F2 F2
$ while read -r l; do sed 's/\t/\n/g' <<< "$l" | uniq | paste -s; done < test
A B1 C1
B B2 D2
C C12 C13
D D3 D5 D9
G F2
注意:该解决方案将不是适用于多行的重复项,C1
例如
A B1 B1 C1
C1 B B2 D2
答案3
也许是这样的:
gawk -vRS='\\s*\\S*' -vORS= '{$0=RT};$1!=prev;{prev=$1}'
RS=pattern
...技巧{$0=RT}
允许您处理定义为与模式匹配的部分的记录。
所以在这里,我们将输入切成<whitespace><non-whitespace>
$0
记录,<non-whitespace>
进入$1
(第一个也是唯一的字段)。我们正在打印$1
不等于前一条的记录。
在这样的输入上:
A B1 B1 C1
B B2 D2
C C12 C13 C13
D D3 D5 D9
G F2 F2
记录是:
[A][ B1][ B1][ C1][ B][ B2][ D2][ C][ C12][ C13][ C13][ D][ D3][ D5][ D9][ G][ F2][ F2][ ]
但不适用于您的第二个示例,请注意它可能会删除一些换行符。
答案4
和perl
:
每行都有独特的单词:
perl -MList::Util=uniq -lape '$_ = join "\t", uniq @F'
全球唯一的单词:
perl -lape '$_ = join "\t", grep {!$count{$_}++} @F'
或者只考虑从第二行开始的每行单词:
perl -lape '$_ = join "\t", shift(@F), grep {!$count{$_}++} @F'