n個のファイルの通信

n個のファイルの通信

n個(つまり、2個以上)ファイルの通信機能を探しています。

man comm内容は次のとおりです。

COMM(1)

NAME
       comm - compare two sorted files line by line

SYNOPSIS
       comm [OPTION]... FILE1 FILE2

DESCRIPTION
       Compare sorted files FILE1 and FILE2 line by line.

       With no options, produce three-column output.
       Column one contains lines unique to FILE1,
       column two contains lines unique to FILE2,
       and column three contains lines common to both files.

このアイデアを説明するために、Bashで最適化されていない最初の別の形式の方法は次のとおりです。

user@host MINGW64 dir
$ ls
abc  ac  ad  bca  bcd

user@host MINGW64 dir
$ tail -n +1 *
==> abc <==
a
b
c

==> ac <==
a
c

==> ad <==
a
d

==> bca <==
b
c
a

==> bcd <==
b
c
d

user@host MINGW64 dir
$ bat otherdir/ncomm.sh
───────┬───────────────────────────────────────────────────────────────────────
       │ File: otherdir/ncomm.sh
───────┼───────────────────────────────────────────────────────────────────────
   1   │ #!/usr/bin/env bash
   2   │ ALLENTRIES=$(sort -u "$@")
   3   │ echo "all $*" | tr " " "\t"
   4   │
   5   │ for entry in $ALLENTRIES; do
   6   │     >&2 echo -en "${entry}\t"
   7   │     for file in "$@"; do
   8   │         foundentry=$(grep "$entry" "$file")
   9   │         echo -en "${foundentry}\t"
  10   │     done
  11   │     echo -en "\n"
  12   │ done
───────┴───────────────────────────────────────────────────────────────────────

user@host MINGW64 dir
$ time otherdir/ncomm.sh *
all     abc     ac      ad      bca     bcd
a       a       a       a       a
b       b                       b       b
c       c       c               c       c
d                       d               d

real    0m12.921s
user    0m0.579s
sys     0m4.586s

user@host MINGW64 dir
$

これにより、列ヘッダーがstderrに表示されます。最初の列「all」には、2つのファイルのうちの1つ(ソート済み)で見つかったすべての項目が含まれ、引数リスト内のファイルごとに1つの列がその行にその項目とともに表示されます。 grepは最初の列と行を超えてすべてのセルに対して一度呼び出されますが、これは本当に遅いです。

commの場合、この出力はidなどの短い行/項目にのみ適用されます。よりきれいなバージョンは、2+列の各項目に対してxまたは類似のものを出力します。

これは、Windows MSYS2のGitとRHELで動作します。

これをより効率的な方法でどのように達成できますか?

答え1

meld(ただし、グラフィックプログラムです。)ファイル間の3方向比較(例:n = 3)を管理することは依然として可能ですが、より大きなファイルの場合、これを実装することはますます計算的に複雑になるため、そうですdiff(または)ツールです。 。comm

答え2

次の方法を試すことができます。次の特徴があります。

  • 出力はあなたの例に正確に従います。
  • 処理中に値がソートされます。
    • =>事前ソートはスキップできます。
    • =>元の注文は維持されません
  • 入力ファイル名がソートされます。
  • 重複値がクリーンアップされ、マージされて一度だけ表示されます(したがって、重複値で奇妙な動作を示すスクリプトのバグも修正されました)。
  • 組み込みの配列整列機能を使用するため、最新のGNU AWKが必要です。
  • UNIX行の仕上げに合わせてカスタマイズされており、さまざまな行末スタイルを混在させると奇妙な効果が発生する可能性があります。 (プログラムの場合、「a」と「a\r」は異なります!)

コードをテキストファイルに保存して実行権限を提供すると、それをシェルスクリプトのドロップイン代替として使用できます。処理速度が向上します。 (実際には何倍にもなります。) :)

#!/usr/bin/gawk -f
{
    all[$0]
    filenames[FILENAME]
    input[$0,FILENAME]=$0
    # if you only wanted to to mark existence
    # then uncomment the following line 
    # input[$0,FILENAME]="*"
}

END {
    PROCINFO["sorted_in"]="@ind_str_asc"
    printf "all"
    for (i in filenames) {
        printf("\t%s",i)
    }
    for (i in all) {
        printf("\n%s",i)
        for (j in filenames) {
            printf("\t%s",input[i,j])
        }
    }
    print ""
}

関連情報