如何删除制表符分隔的文本文件中的重复值

des*_*esu 6 text-processing csv-simple

我有一个制表符分隔的列文本,如下所示

A      B1      B1     C1
B      B2      D2 
C      C12     C13    C13
D      D3      D5      D9
G      F2      F2   
Run Code Online (Sandbox Code Playgroud)

我怎么能像下面这样转换上表

A      B1     C1
B      B2     D2 
C      C12    C13
D      D3     D5     D9
G      F2   
Run Code Online (Sandbox Code Playgroud)

我已经提取了我的真实数据文件,它是一个制表符分隔的文件,我已经尝试过你(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
Run Code Online (Sandbox Code Playgroud)

输出需要如下

A  CD274    CD276   PDCD1LG2
B  NEK2     NEK6    NEK10     NEKL-4
C  TNFAIP3  OTUD7B
D  DUSP16   DUSP4   DUSP8     VHP-1
E  AGO2
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 7

第一组示例数据:

$ 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
Run Code Online (Sandbox Code Playgroud)

第二组示例数据(相同的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
Run Code Online (Sandbox Code Playgroud)

该脚本file逐行读取输入文件,并为每一行遍历每个字段,构建输出行r. 如果字段中的值已添加到输出行(由已t用字段值的查找表确定),则该字段将被忽略,否则将被添加。

当输入行的所有字段都被处理后,构建的行被输出。

输出字段分隔符-vOFS='\t'在命令行上设置为 Tab through 。


awk脚本揭开:

{
    r = ""
    delete t

    for (i = 1; i <= NF; ++i) {
        if (!t[$i]++) {
            r = r ? r OFS $i : $i
        }
    }

    print r
}
Run Code Online (Sandbox Code Playgroud)

  • 有关等价于 `delete t` 的 POSIX,请参见 `split("", t)` (2认同)

des*_*ert 6

sed/tr、uniq 和粘贴

while read -r l; do sed 's/\t/\n/g' <<< "$l" | uniq | paste -s; done < test
Run Code Online (Sandbox Code Playgroud)

或符合 POSIX:

while read -r l; do echo "$l" | tr '\t' '\n' | uniq | paste -s -; done < test
Run Code Online (Sandbox Code Playgroud)

对于文件,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
Run Code Online (Sandbox Code Playgroud)

:该解决方案将不会超过多行,例如,重复的工作C1

A       B1      B1      C1
C1      B       B2      D2
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 6

也许是这样的:

gawk -vRS='\\s*\\S*' -vORS= '{$0=RT};$1!=prev;{prev=$1}'
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

记录是:

[A][ B1] [ B1] [ C1][
B][ B2][ D2][ 
C][ C12][ C13] [ C13] [
D][ D3][ D5][ D9][
G][ F2] [ F2] [
]

但是不适用于您的第二个示例,请注意它可能会删除一些换行符。

  • @desu,无论您想说什么来澄清您的问题,请在您的问题中对其进行编辑。你可能想参加 [tour](/tour) 以获得一些关于如何提出好问题的建议。 (3认同)