特定の列に重複した値を持つファイルのすべての行を印刷する方法

特定の列に重複した値を持つファイルのすべての行を印刷する方法

次のファイルが与えられた場合:

1,768,12,46576457,7898
1,123,435,134,146
2,345,6756856,12312,1311
5,234,567465,12341,1341
1,3245,4356345,2442,13
9,423,2342,121,463
9,989,342,121,1212

列1の値が少なくとも2回(列1で)表示されるように、すべての行を(bash端末で)リストしたいと思います。結果は

1,768,12,46576457,7898
1,123,435,134,146
1,3245,4356345,2442,13
9,423,2342,121,463
9,989,342,121,1212

答え1

ファイル全体をメモリーに保存したくない場合は、次のようにします。

awk -F , '
  !count[$1]++ {save[$1] = $0; next}
  count[$1] == 2 {
    print save[$1]
    delete save[$1]
  }
  {print}'

答え2

Perlソリューション:

perl -F, -ane ' $h{ $F[0] } .= $_
                }{
                $h{$_} =~ tr/\n// >= 2 and print $h{$_} for keys %h
              ' < input-file
  • -n入力を1行ずつ読みます。
  • -a上記の各行-F(コンマなど)を配列@Fに分割します。
  • %h行は最初のフィールド()で$F[0]入力されたハッシュに保存されます。互いに接続されています(.=)。
  • ファイルの終わり(「Eskimogreeting」)でキーを繰り返し(演算子を}{使用して)改行数を計算します。tr2以上の場合は、保存した行を印刷します。

| sort -n最初の列を数字でソートするには、出力をに提供できます。

注目:最後の行が改行文字で終わらない場合、そのグループはサイズを1として報告します。chomp各行に改行を直接追加するか、文字列配列の代わりに行配列を使用して問題を解決できます。

答え3

awkを使用する(多次元配列のためのGNU awk)

gawk -F, '
    { line[NR] = $0; count[$1]++; found[$1][NR] = 1}
    END {
        for (id in count)
            if (count[id] > 1)
                for (nr in found[id]) 
                    print line[nr]
    }
' file

出力順序は入力ファイルの順序と異なる場合があります。

答え4

Python 3の使用:

#!/usr/bin/env python3
import sys
from collections import defaultdict

column_delimiter = sys.argv[1]
column = int(sys.argv[2]) - 1

records = defaultdict(list)
for l in sys.stdin:
    l = l.rstrip('\n')
    r = l.split(column_delimiter)
    records[r[column]].append(l)

for ll in records.values():
    if len(ll) > 1:
        print(*ll, sep='\n')

使用法:

python3 duplicate-columns.py COLUMN-DELIMITER COLUMN

例:

python3 duplicate-columns.py ',' 1 < data.csv

関連情報