Grep 或 awk 在 2 个大文件之间,其中 file1 是模式文件,file2 包含数据

Grep 或 awk 在 2 个大文件之间,其中 file1 是模式文件,file2 包含数据

File1有固定长度的数字,每行一个数字:

1234
5678
1345

File2包含“key=value”格式的数据字段:

abc:def=1999,xyz=1234;
abc:def=5678,xyz=1234;
abc:def=1234,xyz=5678;

我需要获取字段与 中的任何数字匹配的那些行File2defFile1xyz字段在模式匹配时被忽略。所以,我的结果应该是这样的:

abc:def=5678,xyz=1234;
abc:def=1234,xyz=5678;

答案1

我总是忘记大多数awk命令,这对我的老大脑来说太多了,所以我提供了一个sed替代方案

sed '/^[0-9]*$/H;G;/def=\([0-9]*\),.*\n\1/P;d' file1 file2

这个想法是收集保留空间中的数字file1并使用反向引用来识别 file2 中包含以下数字的那些行:def=

  • 该模式^[0-9]*$匹配仅包含数字的行,这些行是file1行,我们将其附加到H旧空间
  • G将保留空间附加到模式空间,因此我们拥有模式空间中file2的行和所有数字file1
  • 该模式寻址在换行符之后重复/def=\([0-9]*\),.*\n\1后面的数字(反向引用)的所有行(因此它是保留空间集合的一部分)。打印那些没有附加内容的行def=\1P
  • d抑制进一步的输出。你可以使用选项-n代替

更新:视觉解释

正如埃德指出的那样,我的解释显然对每个人都没有帮助。如果您更像是一个“视觉思考者”,我将尝试说明其中的原理。请记住,这sed不是编程工具,而更像是一个带有以下功能的自动文本编辑器保留空间作为“剪贴板”,而行被读入模式空间,工作完成的地方。

现在我按照建议在HG命令后显示两个空格:

模式空间 保留空间 评论
1234 1234 附加H到(空)保留空间并嵌入换行符
1234␤␤1234 1234 追加G回模式空间,添加另一个换行符
5678 ␤␤12345678 读取下一行时保留保留空间,因此下一行H会附加下一个数字
5678␤␤␤12345678 ␤␤12345678 再次追加回模式空间,但仍然与def=模式不匹配
file1为了便于阅读,跳过第三行
abc:def=1999,xyz=1234; ␤␤12345678 与模式不匹配^[0-9]*$,因此H不执行
abc:def=1999,xyz=1234;␤␤␤12345678 ␤␤12345678 G被执行

P现在看看如何应用命令的地址模式(\n用作换行符的占位符):

abc:def=1999,xyz=1234;\n\n1234\n5678
    def=####,         .*                 #### stands for `[0-9]*`, but the back reference
                                         as `\1` is not found: no match

abc:def=5678,xyz=1234;\n\n1234\n5678
    def=####,         .*      \n####     here, the match is repeated as `\1`,so we know
                                         the `def` number has been listed in `file1` 

答案2

将数字收集到散列中(nums在本例中),并使用它来方便以后查找:

awk -F '[=,;]' 'FNR==NR { nums[$1]; next } $2 in nums' file1 file2

输出:

abc:def=5678,xyz=1234;
abc:def=1234,xyz=5678;

如果字段的顺序不是恒定的,则可以使用以下方法:

awk -F'[=,;:]' '
  FNR==NR { nums[$1]; next }
  $2 == "def" && ($3 in nums) || $4 == "def" && ($5 in nums)
' file1 file2

答案3

grep -f <(sed 's/^/abc:def=/' file1.txt) file2.txt

或者,如果您的 shell 不支持,您可以创建一个新文件<()

sed 's/^/abc:def=/' file1.txt > patterns.txt
grep -f patterns.txt file2.txt

或者您可以创建一个 fifo 文件:

mkfifo fifo
sed 's/^/abc:def=/' file1.txt >fifo &
grep -f fifo file2.txt

相关内容