web-dev-qa-db-ja.com

複数のファイルから共通の番号を見つける方法は?

すべてのファイルに存在する共通の番号を抽出したい。フォルダに1000個のファイルがあります。すべてのファイル番号を比較して、1000ファイルの共通番号を見つけたい。私は以下のコードを使用しました:

for ((i=2;i<=10000;i++))  
do
comm -12 --nocheck-order a.txt "$i".txt > final.txt
mv final.txt file.txt
done

ただし、最後のファイルのみをa.txtと記述して比較するだけです。しかし、私はすべてのファイルに共通の番号が存在することを望んでいます。

a.txtファイルとしましょう:

1
3
47
8
6
7

1.txtファイル:

2
3
6
7
8

2.txtファイル:

3
5
6
7
9

3.txtおよび4.txt .... 1000.txt。これがこの3つのファイルで正常に機能する場合は、すべてのファイルで正常に機能するはずです。このファイルで非常に一般的なのは次のとおりです。

3
7

それが私に与えている間

3
8
3

どうすれば続行できるか教えてください。

2
claudia smith

各番号がファイルに1回しか表示されないと仮定します。

$ awk '{c[$1]++} END{for (i in c) if (c[i] == (ARGC-1)) print i}' a.txt {1..2}.txt
3
6
7
1
Ed Morton

他の問題に加えて、スクリプトループがcommを10000回呼び出しているため、非常に遅くなっています。より高速な代替方法は、それらすべてをソートして繰り返しをカウントすることです。ファイルの数に等しい数の行がすべてのファイルに存在します(各ファイル内の値が繰り返されていない場合)。

set -- ./*.txt
sort -n "$@" | uniq -c | awk -vcount="$#" '$1==count{print $2}'

私は両方にファイルのリストを持つために位置引数を使用しています"$@"およびファイルの数$#

ソートは数値です-nnumberを要求すると。

次のような番号が繰り返されているファイルがないことをチェック(およびソート)できます。

set -- ./*.txt

for    f; do
       sort -n "$f"          > "$f.tempfile"
       mv      "$f.tempfile"   "$f"
       if [ "$(uniq -d "$f")" != "" ]; then echo $f; fi
done

これにより、番号が繰り返されているすべてのファイルが一覧表示され、個々のファイルが並べ替えられます。

0
Isaac

問題は、各反復で出力を上書きすることです。 >リダイレクトは、リダイレクト先のファイルを切り捨て(空)にします。

別のアプローチ:各ファイルをsort -uで個別に並べ替えて、そのファイルに固有のエントリを取得し、これらの並べ替え操作の結果を連結してsort | uniq -cに渡し、各エントリの回数の合計を取得します。すべてのファイルに表示されます。次に、その結​​果を調べて、ファイルの数に等しいカウントを持つエントリを選択します。これらは、すべてのファイルで発生するエントリです。

set -- ./*.txt

for file do
    sort -u "$file"
done | sort | uniq -c |
awk -v c="$#" '$1 == c { print $2 }'

ここでは位置パラメーターを使用して、set -- ./*.txtで反復処理するファイルのリストに設定しています。これは、後で$#を使用できるようにするためです。これは、リスト内のファイルの数です。

表示する最初の3つのデータセットの場合、これは次のように出力されます。

3
6
7
0
Kusalananda

commが複数のファイル間の共通行を正しく報告するためには、入力ファイルがまだソートされていない場合は、ソートされたとおりに渡す必要があることを最初に知ってください。

2つ目は、mvコマンドをmv final.txt a.txtに変更する必要があることです。前の試行の結果に対して次のファイルをチェックするため。ここでは、a.txtからバックアップを取り、代わりにcommon.txtをforループでの反復に使用しました。

したがって、最終的なスクリプトは次のようになります。

cp a.txt common.txt
for ((i=1;i<=10000;i++));
    do comm -12  <(sort common.txt) <(sort $i.txt) >temp.txt;
    mv temp.txt common.txt;
done

最後に、cat common.txtは、10000ファイル間で共通の行になります。

0
αғsнιη

commは、ソートされたファイル専用です。

sortedファイルFILE1とFILE2を1行ずつ比較します。

ソース: https://linux.die.net/man/1/comm

そのため、アルゴリズムはソートされていないファイルでは機能しません。これは動作します:

#!/bin/sh

sort -n a.txt > tmp.txt

END=4

for i in `seq 2 $END`
do
comm -12 --nocheck-order tmp.txt $i.txt |tee tmp.txt
done
cp tmp.txt "final.txt"

一部のシステムでは、|teeの代わりに>演算子を使用することもできます(ファイルへの書き込みと上書き)

0
ralf htp