ほぼ重複した行を削除

ほぼ重複した行を削除

解決策がわからない難しい問題があります。

何百万行ものテキストを含むテキストファイルがあります。基本的には実行したいのですが、uniqいくつかのバリエーションがあります。 2行が同じですが、サフィックスがある場合は、:FOOサフィックスが欠落している行を削除します。しかし、ただそれ以外の場合、行が同じ場合。そしてただfor :FOO、他の可能な接尾辞の代わりに。するいいえ/usr/bin/delta:FOO上記の行が同じではないので削除したいと思います。

red.7
green.2
green.2:FOO
blue.6
yellow.9:FOO

green.2下の行は同じですが、接尾辞がついて削除したいと思います。他のすべての行は変更されていないままにしてください。

[編集する:ファイルがすでに順番に整理されていることに言及するのを忘れました。 ]

これまで私の考え:

  • 明らかにuniqこれを行うツールです。
  • uniq一つは無視してもいいプレフィックスしかし、決してサフィックス。 (これはとても迷惑なことです!)
  • 私はそれが:フィールドセパレータであるかのように偽装し、cut(と一緒にpaste)フィールドシーケンスを反転できると思いました。しかし、いいえ、cut区切り文字がないと空白行を強制的に出力することは明らかに不可能です。
  • 次のアイデアは、行を段階的に進め、サフィックスがあるかどうかに応じて1文字のプレフィックスを出力することです。しかし、これを高性能のBashループで書くことは想像できません。

どのようなヒントがありますか?

ただ使用することができます。本物この問題を解決するためのプログラミング言語の Bash で修正することは十分簡単ですが、うまくいきませんでした。

ベストアンサー1

最も簡単な場合は、行なしで削除するには削除してから:FOOuniqを渡すだけです:FOO

$ sed 's/:FOO$//' file | uniq
red.7
green.2
blue.6
yellow.9

行を保持し:FOO、接尾辞のない兄弟の後ろに常に来ると仮定する場合は、次のことを試すことができます。

$ rev file | sed 's/:/ /' | uniq -f1 | sed 's/ /:/' | rev
red.7
green.2:FOO
blue.6
yellow.9:FOO

rev各行を右から左に印刷します。最初のフィールドを空白に置き換えると、sed認識(またはこの場合)を無視する必要がある最初のフィールドとして使用できます。次の sed はその後に次のフィールドを配置し、最後のフィールドは左から再印刷されます。右。:uniqFOOOOF:rev


残念ながら、文書が主張する内容にもかかわらず、uniqフィールド区切り文字としてスペースやタブだけでなく、英数字ではなく、ほぼすべての文字を使用します。

$ printf 'foo/1\nfoo/2\nfoo%%3\nfoo:4\n' 
foo/1
foo/2
foo%3
foo:4
$ printf 'foo/1\nfoo/2\nfoo%%3\nfoo:4\n'  | uniq -f1
foo/1

これは、対応する文字がある場合、上記の回避策が機能しないことを意味します。あるいは、ファイルのすべてのインスタンスを削除し、結果を新しいインスタンスにgrepパターンリストとして提供することで、次のことを回避できます。:FOO:FOOgrep

$ grep -hFxv "$(grep ':FOO' file | cut -d: -f1)" file 
red.7
green.2:FOO
blue.6
yellow.9:FOO

おすすめ記事