テキストフィールドを含むタブで区切られたデータファイルがあり、その一部にはセミコロンで区切られ、繰り返される情報があります。
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>foo
TABと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
-n
perl -F'\t' -ane '...'