重複した情報を含むテキストフィールド

重複した情報を含むテキストフィールド

テキストフィールドを含むタブで区切られたデータファイルがあり、その一部にはセミコロンで区切られ、繰り返される情報があります。

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

POSIX的に:

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>fooTABと2番目のフィールドは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-nperl -F'\t' -ane '...'

関連情報