【问题标题】:Remove Line If It Contains Exact String From Line Of Another File如果该行包含另一个文件的行中的确切字符串,则删除该行
【发布时间】:2019-05-30 17:52:39
【问题描述】:

我有一个大文件,想从文件中删除包含另一个文件中列出的确切字符串的所有行。但是,字符串必须完全匹配(对不起,我不知道如何更好地描述这一点)。

这是文件:

one@email.com,name,surname,city,state
two@email.com,name,surname,city,state
three@email.com,name,surname,city,state
anotherone@email.com,name,surname,city,state

这里是过滤的示例列表:

one@email.com
three@email.com

想要的输出是:

two@email.com,name,surname,city,state
anotherone@email.com,name,surname,city,state

我尝试使用以下方法来做到这一点:

grep -v -f 2.txt 1.txt > 3.txt

但是这会产生输出:

two@email.com,name,surname,city,state

我认为它这样做是因为“anotherone@email.com”包含“one@email.com”。我已经搜索了一种包含行首的方法,但没有找到任何合适的方法。

我也愿意做 grep 以外的事情,我使用 grep 是因为我想不出任何其他方式。

【问题讨论】:

  • three@email.com != three@gmail.com
  • 如果你使用 GNU grep 添加选项 -w.

标签: awk sed grep


【解决方案1】:

假设您的输入文件包含three@gmail.com 而不是three@email.com(可能是错字)

$ grep -vw -f 2.txt 1.txt
two@email.com,name,surname,city,state
anotherone@email.com,name,surname,city,state

-w, --word-regexp - 表达式作为单词搜索(好像被[[:<:]]' and[[:>:]]'包围;

【讨论】:

  • 这可能有些危险,因为它不仅在文件的第一个字段中搜索过滤器,而且在行的任何地方都搜索。因此,如果在末尾找到该单词,它也会删除整行。前任。它将删除此行anotherone@email.com,name,surname,city,state,three@email.com
  • @Jotne,OP 没有说明搜索 “在文件的 first 字段中”的规则
  • 没错,这就是为什么 OP 应该阅读我的评论并看到如果在行中的任何位置找到过滤器数据并且他只查找第一个字段,则此解决方案确实删除了该行。您的解决方案可能适用于 OP。
  • @Jotne 好的,让我们等待 OP 的反应
  • 抱歉,回复晚了 - 电子邮件仅在第一个字段中找到,因此可以按预期工作。但是,由于输入的大小,这很快就会产生内存错误。
【解决方案2】:

如果您只想打印第一个文件中does not 在第一个字段中包含来自第二个文件的数据的行,那么应该这样做:

$cat file
one@email.com,name,surname,city,state
two@email.com,name,surname,city,state
three@email.com,name,surname,city,state
anotherone@email.com,name,surname,city,state
$cat filter
one@email.com
three@email.com

awk -F, 'NR==FNR {a[$0]++;next} !($1 in a)' filter file
two@email.com,name,surname,city,state
anotherone@email.com,name,surname,city,state

对于filter 中的每一行,这将创建一个数组a,其名称和值为1
喜欢a[one@email.com]=1a[three@email.com]=1
然后awkfile对数组中逐行测试,给出

a[one@email.com]=1
a[two@email.com]=
a[three@email.com]=1
a[anotherone@email.com]=

然后打印从file 中没有1 的所有行

two@email.com,name,surname,city,state
anotherone@email.com,name,surname,city,state

【讨论】:

  • 与我正在使用的两个大型文件完美配合。非常感谢。
【解决方案3】:

对于这种特殊情况——通过构建一个关联数组来处理第一个文件,其中过滤器行是索引。在后续文件中,测试给定行是否不在数组索引中——模式的默认操作是打印。

awk -F, -v OFS=, '
    BEGIN   { split("", m) }
    NR==FNR { m[$0] = ""; next }
    !($1 in m)
' filter.txt file.txt

但是...如果我们要过滤行中任意位置出现的字符串(不受约束的完全匹配),我们需要做一些不那么聪明和更暴力的事情:

awk '
    BEGIN {
        split("", m)
        n=0
    }
    NR==FNR {
        m[n++] = $0
        next
    }
    {
        for (i=0; i<n; ++i) {
            if (index($0, m[i]))
                next
        }
        print
    }
' filter.txt file.txt

请注意,如果过滤器包含不可打印的字符(例如非 unix 行尾),我们需要通过过滤掉它们来处理它们(例如使用sub(/\r/, ""))。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多