複数のファイル(必ずしも2つのファイルである必要はありません)の交点を見つけるには?

複数のファイル(必ずしも2つのファイルである必要はありません)の交点を見つけるには?

交差点を見つけるための簡単なスクリプトを作成したいと思います。複数のファイル(すべてのファイルの共通行)、したがって一部の項目を読んだ後(協会)bashスクリプトを作成しようとしましたが、残念ながら失敗しました。私は何が間違っていましたか?

RES=$(comm -12 ${1}  ${2})

for FILE in ${@:3}
do
    RES=$(comm -12 $FILE  ${RES})
done

parallelまたはを使用してこれを達成する方法に関する他の提案はありますかxargs

答え1

関数は再帰的な方法を受け入れます。

f() {
     if (($# == 1))
     then
         cat $1;
         return;
     fi
     comm -12 $1 <(f "${@:2}")
}

f file1 file2 file3 file4 file5...

答え2

逆参照するときRES

comm $FILE  ${RES}

content RESreplacement ${RES}。ただし、引数としてファイルcomm名が必要です。たとえば、$RES含まれています。hello commhello

代わりに、一時ファイルを使用してプロシージャ内に共通の行を保存できます。

tmp=$(mktemp --tmpdir)
tmp2=$(mktemp --tmpdir)
comm -12 ${1}  ${2} >$tmp

for FILE in ${@:3}
do
    comm -12 $FILE  $tmp >$tmp2
    rm $tmp 
    mv $tmp2 $tmp   
done

cat $tmp 
rm $tmp

答え3

いいえparallel、必要xargsありませんcomm。機能を試してください

$ intersection() {  sort $@ | uniq -c | sed -n "s/^ *$# //p"; }
$ intersection file[1-3]
line2
line4

答え4

問題は、comm2つのファイルが必要であり、$RES変数であることです。

しかし、私たちはできます。だまされるそして、プロセス置換を使用してファイルのように見えます。

#!/bin/bash

RES=$(comm -12 ${1}  ${2})

for FILE in ${@:3}
do
    RES="$(comm -12 $FILE  <(printf %s "${RES}"))"
done

printf %s "$RES"

ご覧のとおり、ソースとほぼ同じですが、構造を使用して<(...)コマンドを実行し、それをファイル名として使用しています。

したがって、次の3つのファイルがある場合:

a:line1
a:line2
a:line3
a:line4
b:line2
b:line4
b:line6
c:line2
c:line4
c:line8

私たちはそれらを比較できます:

% ./allcomp a b c
line2
line4

関連情報