查找一个文件的任何行是否是另一个文件中数据的子集

查找一个文件的任何行是否是另一个文件中数据的子集

file1.txt我有一个包含以下数据的文件:

MIME_HTML_ONLY
SUSPICIOUS_RECIPS
SORTED_RECIPS
HFILTER_HELO_5

另一个文件file2.txt的行如下:

HFILTER_FROM_BOUNCE FORGED_OUTLOOK_HTML
SORTED_RECIPS HFILTER_HELO_5
MIME_HTML_ONLY HFILTER_FROM_BOUNCE
SUSPICIOUS_RECIPS ANY_OTHER_WORD
:
:

我想找到谁的数据中的所有行file2.txt(该行的所有单词)是中存在的数据的子集file1.txt

例如对于输出上面应该是这一行: SORTED_RECIPS HFILTER_HELO_5

现在我可以循环并读取 的各个行file2.txt,看看它是否是 的子集file1.txt。但我必须为 1000 个不同的file1.txt's.因此,循环遍历file2.txtfor every的各个行file1.txt非常慢。有什么有效的方法可以使用 来做到这一点吗awk sed grep

答案1

awk 'FNR == NR && $0 !~ /^[[:blank:]]*$/ { Dict[$0] = 1 }
     FNR != NR {
        i = 1
        while( i <= NF && Dict[ $i] == 1) i++
        if( i > NF) print
        }
    ' File1.txt File2.txt
  • 通用,不依赖于 file2 每行的字段/字数
  • 处理两个文件的已排序和未排序内容
  • 使用内存加载第一个文件字典所以如果要验证大量单词,可能不是最好的
  • 提供给 awk 的文件顺序是强制性的
    • 第一个是字典参考
    • 任何(至少 1)个其他都是要过滤的文件

概念:

  • 使用值作为索引加载数组中的每个单词
    • 取值1(未赋值默认为0)
    • 来自第一个文件 [其中 FNR(文件记录号)= NR(自第一次打开文件以来的记录号),默认情况下,一条记录是 awk 中的一行]
    • 空行上有一个过滤器(没有字符或只有空格)
  • 初始化计数器 (i)
  • 将每个字段(默认情况下由于空格分隔符而导致此处的单词)与字典中的对应字段进行比较。如果存在(值 = 1),则循环到下一个字段并递增计数器 (i)
  • 循环后,如果计数器(i)大于字段(单词)的数量,则所有单词都匹配,我们打印该行
  • 循环到下一行条目

答案2

以下脚本将编译file1.txtgrep -E.

#!/bin/sh
regex="^($(awk '{printf $0"|"}' $1) )+\$"
grep -E "$regex" $2

用法:

$ ./script.sh file1.txt file2.txt 
SORTED_RECIPS HFILTER_HELO_5

$regex编译自file1.txt如下:

^(ME_HTML_ONLY|SUSPICIOUS_RECIPS|SORTED_RECIPS|HFILTER_HELO_5| )+$

对于数千行file1.txt和数file2.txt百万行,最好使用file1.txt's以下脚本将所有行编译成单个 awk 程序:

#!/bin/sh
for i; do
        regex="^($(awk '{printf $0"|"}' $i) )+\$"
        echo "/$regex/ { print \"$i: \"\$0 }"
done

例如(file1.txt's命名为match1.txt match2.txt match3.txt):

$ ./script2.sh match*.txt 
/^(ME_HTML_ONLY|SUSPICIOUS_RECIPS|SORTED_RECIPS|HFILTER_HELO_5| )+$/ { print "match1.txt: "$0 }
/^(HFILTER_FROM_BOUNCE|FORGED_OUTLOOK_HTML|ANY_OTHER_WORD| )+$/ { print "match2.txt: "$0 }
/^(SORTED_RECIPS|HFILTER_HELO_5|MIME_HTML_ONLY|HFILTER_FROM_BOUNCE| )+$/ { print "match3.txt: "$0 }

$ ./script2.sh match*.txt >match.awk
$ awk -f match.awk file2.txt 
match2.txt: HFILTER_FROM_BOUNCE FORGED_OUTLOOK_HTML
match1.txt: SORTED_RECIPS HFILTER_HELO_5
match3.txt: SORTED_RECIPS HFILTER_HELO_5
match3.txt: MIME_HTML_ONLY HFILTER_FROM_BOUNCE

相关内容