grep
2つのファイル間で一致する行を見つけるために使用します。
grep -w -f file1.txt file2.txt > file3.txt
に一致しない行を-v
提供できるフラグがあることを知っています。で一致しない行を取得する方法はありますか?各行にはより多くのテキストがあるため、位置を変更することは機能しません。file2.txt
file1.txt.
file1.txt
file2.txt
file2.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