ファイルを収集するときに最初のファイルから一致しない行を収集するにはどうすればよいですか?

ファイルを収集するときに最初のファイルから一致しない行を収集するにはどうすればよいですか?

grep2つのファイル間で一致する行を見つけるために使用します。

grep -w -f file1.txt file2.txt > file3.txt

に一致しない行を-v提供できるフラグがあることを知っています。で一致しない行を取得する方法はありますか?各行にはより多くのテキストがあるため、位置を変更することは機能しません。file2.txtfile1.txt.file1.txtfile2.txtfile2.txt

デフォルトでは、file1.txt空白のない単一のID列を持つテキストファイルですが、file2.txtタブで区切られた列とfile1.txt。だから私が見つけたいのは、file2.txt一致するIDがない行ですfile1.txt

実際、もう別の質問から答えを見つけたようです。 "Ungrep" - 一致しないパターン

答え1

この答えは、@danvoronovの初期の投稿と未使用のキーを取得するための@waltinatorのソリューションを組み合わせることで、両方を改善しました。

私は、プリンストンCS50コース資料の英語セットからランダムに選択されたBashとawkビルテストファイルの約60行を持っています。私はまた、単一のプロセスでこの問題を解決するために30行のBashとawkを持っています。パフォーマンスの向上が必要なため、まだ公開していません。

私のスクリプトと以下の公開スクリプトは同じ結果を生成します。参照および検査の目的で、各出力テキストの前には元のファイルの行番号が続きます。テストファイルは、file1の短いレコード15,000個(file2と一致する12,000個、一致しない3,000個、平均長92文字)とfile2の合計20,000行(平均長129文字)で構成されています。

キーは、行のランダムな単語で始まり、ランダムな数の単語(少なくとも4つ)を取るより大きなレコードのランダムな選択から取得されます。

単一のキーが複数のレコードと一致することがあります。私たちは一対一のペアリングを強制しません。

以下の公開スクリプトは、その量のデータを実行するのに約1分30秒かかります(私のawkは5分45秒かかりました)。

file1のデータは有効な正規表現ではない可能性が高いため、-Fオプションをgrepと共に使用する必要があります。プレーンテキストをREと見なすと、* +のような文字がたくさんあります。予期せず一致した場合()[] |エラーが発生します。 -Fはより速いかもしれません。 (600倍向上したのを見ました。そのアルゴリズムが何なのか気になります!)

Unkeyed grepは-qオプションのみを使用し、ステータスは一致が発生したかどうかを示します。これにより、2つのプロセス(file1の各行のサブシェルとwc -l)が節約され、ファイル全体を読み取るのではなく最初の一致で終了するため、読み取ったデータも平均して半分になります。

#! /bin/bash

    grep -n -w -F -f file1.txt file2.txt > file3.txt

    while read -r Key; do
        (( ++Fnr ))
        grep -q -w -F -- "$Key" file2.txt || printf '%d:%s\n' "${Fnr}" "$Key"
    done < file1.txt > file4.txt

一部の初期質問(フィールドのデータ、スペースが重要か、データのサイズ)がまだ回答されていないため、コメントを歓迎します。

答え2

次の行を個別に処理しますfile1.txt

for str in $(cat file1.txt) ; do
    num=$(grep -w "$str" file2.txt | wc -l )
    if [[ $num -eq 0 ]] ; then
        echo "$str"
    fi
done

関連情報