包含重复信息的文本字段

包含重复信息的文本字段

我有一个带有文本字段的制表符分隔数据文件,其中某些字段具有重复信息,以分号分隔:

2000;2000
05/19/2016;05/19/2016
foo;foo

我怎样才能sed删除重复的部分?分号经常出现在其他字段中,所以我想我需要搜索在分号两侧找到的字符串,由制表符绑定,即\t$1;$1\t\t表示制表符),然后替换为$1不带分号和重复的相同实例场地。我对其他文本解析命令持开放态度。

答案1

在文件中使用此内容tabbed.input(没有空格,所有连续的空格都是一个制表符):

abc     bd      c       2000;2000       d       2;00;2;01
e       05/19/2016;05/19/2016   foo;foo f       g

以下Python程序:

def cleaned(f):
    length = len(f)
    if (length % 2) == 0:
        return f  # even number of characters in field, middle one never ';'
    half_way = length // 2
    if f[half_way] != ';':
        return f
    before, after = f[:half_way], f[half_way+1:]
    if before == after:
        return before
    return f

with open('tabbed.input') as fp:
    for line in fp:
        fields = line[:-1].split('\t')
        cleaned_fields = [cleaned(f) for f in fields]
        print('\t'.join(cleaned_fields))

你的输出将是:

012345670123456701234567012345670123456701234567
abc     bd      c       2000    d       2;00;2;01
e       05/19/2016      foo     f       g

通过测试偶数个字符并;在字段中间包含“ ”,当重复数据包含“ ;”时,这甚至可以工作

答案2

POSIXly:

sed -e 's/\([^;][^;]*\);\1/\1/g' <file

您还可以使用:

sed -E 's/([^;]+);\1/\1/g' <file

它得到了 GNU 和 BSD sed 的支持,并将成为下一个 POSIX 的标准。

答案3

perl

perl -F'\t' -e 'map {s/(.+);$1/$1/} @F; print join("\t",@F)'

与该sed解决方案不同,该解决方案单独处理每个字段,从而防止检测和删除跨字段重复的可能性(例如foo;<TAB>foo- TAB 和第二个字段foo被该解决方案删除sed,但不是被该perl解决方案删除)。根据您的输入数据,这在您的实际使用中可能不是问题。

以下版本消除了字段中的多个重复项(例如a;b;a;b;a;b--> a;b):

perl -F'\t' -e 'map {while(/(.+);$1/) {s/(.+);$1/$1/g}} @F;print join("\t",@F)'

注意:这些假设是最新版本的perl,其中-F暗示-a-n。如果您有旧版本,请使用perl -F'\t' -ane '...'

相关内容