web-dev-qa-db-ja.com

grepへのsedの配管が期待どおりに機能しないようです

私は2つのファイルを持っています:

$ cat file1  
jim.smith  
john.doe  
bill.johnson  
alex.smith  

$ cat file2   
"1/26/2017 8:02:01 PM",Valid customer,jim.smith,NY,1485457321      
"1/30/2017 11:09:36 AM",New customer,tim.jones,CO,1485770976     
"1/30/2017 11:14:03 AM",New customer,john.doe,CA,1485771243  
"1/30/2017 11:13:53 AM",New customer,bill.smith,CA,1485771233  

File2から、file1に存在しないすべての名前が必要です。
以下は機能しません:

$ cut -d, -f 3 file2 | sed 's/"//g' | grep -v file1  
jim.smith  
tim.jones  
john.doe  
bill.smith  

この場合、grep -vへのパイプが機能しないのはなぜですか?

2
Jim

これは事実上私の 以前の質問への回答 の最後のステップです。

grep-fの前にfile1を追加すると、ソリューションは機能します。

$ cut -d, -f3 file2 | grep -v -f file1
tim.jones
bill.smith

-fを使用すると、grepfile1でパターンを検索します。これがないと、リテラルパターンとしてfile1を使用するだけです。

-Fを使用することもできます。そうしないと、パターン内のドットが「任意の文字」として解釈されるためです。そして、そこにいる間に、-xもそこに入れて、grepが行全体で一致を実行するようにします(joe.smithがない場合に役立ちます)。一致joe.smiths):

$ cut -d, -f3 file2 | grep -v -F -x -f file1

これには、明らかに、file1の行末に末尾のスペースがないことが必要です(これは、質問のテキストにあるようです)。

sedの出力には"が含まれていないため、cutは必要ないことに注意してください。また、すべての"を削除するためにneededがあれば、tr -d '"'の方が優れたツールでした。

11
Kusalananda

これを試して。いいえsed。 GNU diffおよびbashが必要です。

diff --new-line-format="" --unchanged-line-format="" <(cut -f3 -d, file2|sort) <(sort file1)

歩留まりの結果:

bill.smith
tim.jones
5
steve

これは機能するはずです:

$ pattern=$(cut -d, -f 3 file2)
$ grep -v -e "$pattern" file1  

あなたの例では、grepはそのパターンを見逃しています。さらに、grepはファイルまたはstdin(パイプによる)の両方を読み取ることはできません。ファイル名が指定されていない場合、grepはstdinから読み取ります。

また、これも機能する可能性があります。

$ grep -v -f <(cut -d, -f3 file1) file2  

申し訳ありませんが、テストされていません。

3
George Vasiliou

grep -fの答えはおそらく最良の答えですが、少しスタイリッシュな代替手段は次のとおりです。

% cut -d, -f3 file2 >names2
% cat file1 file1 names2 | sort | uniq -u
bill.smith
tim.jones
%

もちろん、これには追加の一時ファイル(またはファイル記述子を使用した楽しいゲーム)が必要であり、大きなファイルで試してみたいとは思いません。

これについては、ファイル間の照合を含むタスクの場合、sortuniqが予想外に用途が広く、おそらく過小評価されているツールのペアであるためにのみ言及します。迅速なタスクのために、彼らは結果に少し考えが必要な方法を提供することができます。

1
Norman Gray