私はそれぞれ約10,000行を含む60個のファイルを持っています。各行には文字列が含まれています。
すべてのファイルに共通の文字列を見つけたいです。
正確に一致するものが必要なので、行全体を比較します。
答え1
この試み、
awk '
BEGINFILE{fnum++; delete f;}
!f[$0]++{s[$0]++;}
END {for (l in s){if (s[l] == fnum) print l}}
' files*
説明する:
BEGINFILE { ... }
各ファイルの先頭から実行fnum++
ファイルカウンタを増やすdelete f
配列の削除これは使用されますファイルごとの冗長ラインフィルタリング(posix互換ソリューションリンクを参照)
!f[$0]++ { ... }
ファイルの最初の行でのみ実行(f[$0]
0(false)の場合)s[$0]++
行カウンタをインクリメントします。
END { ... }
前回実行for (l in s){if (s[l] == fnum) print l}
行を繰り返し、ファイル数と同じ回数で発生する各行を印刷します。
600,000行はメモリに十分です。それ以外の場合は、s
ブロックより小さいものfnum
をすべて削除する危険がありますBEGINFILE{...}
。
答え2
Bashのパラレルバージョン。メモリより大きいファイルで動作します。
export LC_ALL=C
comm -12 \
<(comm -12 \
<(comm -12 \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 1) <(sort 2);) <(comm -12 <(sort 3) <(sort 4););) \
<(comm -12 <(comm -12 <(sort 5) <(sort 6);) <(comm -12 <(sort 7) <(sort 8);););) \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 9) <(sort 10);) <(comm -12 <(sort 11) <(sort 12););) \
<(comm -12 <(comm -12 <(sort 13) <(sort 14);) <(comm -12 <(sort 15) <(sort 16););););) \
<(comm -12 \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 17) <(sort 18);) <(comm -12 <(sort 19) <(sort 20););) \
<(comm -12 <(comm -12 <(sort 21) <(sort 22);) <(comm -12 <(sort 23) <(sort 24);););) \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 25) <(sort 26);) <(comm -12 <(sort 27) <(sort 28););) \
<(comm -12 <(comm -12 <(sort 29) <(sort 30);) <(comm -12 <(sort 31) <(sort 32);););););) \
<(comm -12 \
<(comm -12 \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 33) <(sort 34);) <(comm -12 <(sort 35) <(sort 36););) \
<(comm -12 <(comm -12 <(sort 37) <(sort 38);) <(comm -12 <(sort 39) <(sort 40);););) \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 41) <(sort 42);) <(comm -12 <(sort 43) <(sort 44););) \
<(comm -12 <(comm -12 <(sort 45) <(sort 46);) <(comm -12 <(sort 47) <(sort 48););););) \
<(comm -12 \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 49) <(sort 50);) <(comm -12 <(sort 51) <(sort 52););) \
<(comm -12 <(comm -12 <(sort 53) <(sort 54);) <(comm -12 <(sort 55) <(sort 56);););) \
<(cat <(comm -12 <(comm -12 <(sort 57) <(sort 58);) <(comm -12 <(sort 59) <(sort 60););) ;);););
ファイルがソートされている場合sort
。cat
答え3
For、ラベル付き配列でzsh
配列交差演算子を使用します。${a:*b}
ユニークフラグ(また、$(<file)
ksh演算子とf
パラメータ拡張フラグを使用して改行を分割する):
#! /bin/zsh -
typeset -U all list
all=(${(f)"$(<${1?})"}); shift
for file do
list=(${(f)"$(<$file)"})
all=(${all:*list})
done
print -rC1 -- $all
(スクリプトはファイルリストを引数として使用し、空白行は無視されます。)
答え4
そしてjoin
:
cp a jnd
for f in a b c; do join jnd $f >j__; cp j__ jnd; done
3つのファイルa、b、cには数字(1-6、3-8、5-9)しかありません。これは、3つすべてに共通する2行(数字、文字列)です。
]# cat jnd
5
6
cp
特にその間にはエレガントでも効率的でもありません。ただし、簡単に並列に動作できます。ファイルサブグループ(for f in a*
)を選択してファイルに一意の名前を付けると、複数のサブグループを一度に実行できます。それでも結果をリンクする必要があります... - 64個のファイルに対してそれぞれ8個のファイルを連結する8個のスレッドがあり、残りの8個のファイルを再び4個のスレッドに分割できます。