通过管道 sed 到 grep 似乎没有按预期工作

通过管道 sed 到 grep 似乎没有按预期工作

我有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 的管道在这种情况下不起作用?

答案1

这实际上是我的最后一步回答你之前的问题

如果您在-f前面添加:file1grep

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

使用-fgrep将查找file1模式。如果没有它,它将简单地用作file1文字模式。

您可能还想使用-Fsince ,否则,模式中的点将被解释为“任何字符”。同时,您-x也可以在其中输入 ,以使grep匹配整个行(如果您有一个joe.smith不应该匹配的 ,这将很有用joe.smiths):

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

显然,这要求行尾没有尾随空格file1(问题的文本中似乎有)。

请注意,不需要 ,sed因为 的输出cut不包含任何"。另外,如果你有需要的删除所有",那么tr -d '"'将是一个更好的工具。

答案2

尝试这个。不sed。需要 GNUdiffbash.

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

产量结果:

bill.smith
tim.jones

答案3

这应该有效:

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

在你的例子中 grep 错过了它的模式。此外,grep 可以读取文件或标准输入(通过管道),但不能同时读取两者。如果未给出文件名,则 grep 从 stdin 读取。

另外,这也可能有效:

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

抱歉,尚未测试。

答案4

答案grep -f可能是最好的,但一个稍微时尚的替代方案是:

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

当然,这确实需要一个额外的临时文件(或带有文件描述符的乐趣和游戏),并且我不想尝试使用大文件。

我提到这一点只是因为,对于涉及文件之间匹配的任务,sortplusuniq是出乎意料的多功能且可能未被充分认识的一对工具。对于快速任务,它们可以提供一种无需思考的方法即可获得结果。

相关内容