" grep -v"在一个文件中搜索不在另一个文件中的条目

时间:2018-03-22 21:54:29

标签: bash grep

尝试使用grep -v但不太成功。 我从选项页面上读到:

  

-v:反转匹配。

file1="/path_to/ID.txt"
file2="/path_to/Large_anno.txt"
file3="/path_to/output.txt"
grep -v $file1 $file2 > $file3

file1如下所示:

1_762443_G_T_b37
1_762491_G_A_b37
1_762494_C_G_b37
1_762523_T_A_b37
1_762525_A_T_b37
1_762526_G_A_b37
1_762527_G_A_b37
1_762531_C_T_b37
1_762536_G_A_b37
1_762536_G_C_b37

文件2的第一列是上述格式,另外90列是其他信息。某些列缺少值。我附上了前16列。

1_762491_G_A_b37    1   762491  762491  G   A   ncRNA_exonic    LINC00115   ncRNA_exonic    ENSG00000225880 0.0001  4.369   0   1   11400   
1_762526_G_A_b37    1   762526  762526  G   A   ncRNA_exonic    LINC00115   ncRNA_exonic    ENSG00000225880 11.75   0   2   3       0.998
1_762527_G_A_b37    1   762527  762527  G   A   ncRNA_exonic    LINC00115   ncRNA_exonic    ENSG00000225880 8.755   0   2   2   0   0.093
1_762541_G_A_b37    1   762541  762541  G   A   ncRNA_exonic    LINC00115   ncRNA_exonic    ENSG00000225880 4.48    0   1   2   0.61    0.988
1_762565_G_A_b37    1   762565  762565  G   A   ncRNA_exonic    LINC00115   ncRNA_exonic    ENSG00000225880 3.964   0   1   3   0.47    
1_762566_C_G_b37    1   762566  762566  C   G   ncRNA_exonic    LINC00115   ncRNA_exonic    ENSG00000225880 4.111   0   0   4   0.192   
1_762631_G_A_b37    1   762631  762631  G   A   ncRNA_exonic    LINC00115   ncRNA_exonic    ENSG00000225880 6.862   0   1   5   0.025   940
1_762637_G_T_b37    1   762637  762637  G   T   ncRNA_exonic    LINC00115   ncRNA_exonic    ENSG00000225880 0.0053  0.00139776          rs201219564 

我的目标是识别file1中不在文件2中并输出到file3的内容。

3 个答案:

答案 0 :(得分:2)

-v将作为字符串参数给出的搜索字符串反转。要将搜索字符串指定为参数而不是文件行,您必须使用-f

grep -vf "$fileWithSearchStrings" "$fileToBeSearched" > "$outputFile"
  

我的目标是识别file1中不在文件2中并输出到file3的内容。

然后你应该试试

grep -vf "$file2" "$file1" > "$file3"

答案 1 :(得分:2)

可能的grep调用是:

grep -vFf <(cut -f1 -d' ' "$file2") "$file1" 

-v Invert match
-F Patterns are just strings, not regular expressions
-f Take the patterns from the specified file, one pattern per line
<(cut -f1 -d' ' "$file2") make an input file by using the `cut` utility
   to extract the first column of file2, where the column is
   terminated with a space character.

将匹配锚定在行的开头是最佳的,但grep没有针对该行的命令行选项。使用-w强制匹配以匹配字边界可能会减少虚假命中。

您也可以使用Gnu join实用程序,但这需要对两个文件进行排序:

join -v1 <(sort -k1b,1 "$file1") <(sort -k1b,1 "$file2")

您可以轻松选择要输出的行:-v1仅在file1中选择行; -v2仅在file2中选择行;省略-v选项会选择两个文件中的行。

joinsort以相同的顺序对文件进行排序非常重要。通常应该是这种情况,但是您的语言环境以整理顺序处理空格的方式会产生奇怪的结果。我在sort命令中添加了推荐的字段选择选项。更安全(也更快一点)就是在&#34; C&#34;中进行排序和连接。域而不是您机器上的默认域:

(LC_ALL=C; join -v1 <(sort -k1b,1 "$file1") <(sort -k1b,1 "$file2");)

另一种选择可能是使用awk。以下打印file1中的行,这些行在file2的第一个字段中未显示:

awk 'NR==FNR{seen[$1]++;next}!seen[$1]' "$file2" "$file1"

要切换它,最简单的解决方案就是颠倒调用中文件的顺序。

第一个条件(读取的总行数等于此文件中读取的行数)将命令限制为第一个文件(在命令行中);该命令标记哈希表中的行,然后跳过其余命令。因此,第二个条件仅在第二个(和后续)文件参数上尝试,如果该行的第一个字段不在seen哈希中,则成功;由于它没有明确的操作,因此使用默认操作来打印该行。

答案 2 :(得分:1)

Here's a trick that is more flexible in some situations. If you combine the lines from multiple files, you can find the unique lines easily. So in your example:

cat "${file1}" "${file2}" "${file2}" | sort | uniq -u > "${file3}"

This is how it works:

  1. cat combines file1 with two copies of file2
  2. sort will sort the lines of the combined files
  3. uniq -u will give you the unique lines, which cannot be from file2 since it is duplicated, and cannot be lines that are found in both file1 and file2

You can use this same method for many more files, catching the unique lines. And if you want to see just the lines in common, that would be:

cat "${file1}" "${file2}" | sort | uniq -d 

Best of luck!