grep 从 file2 中精确提取行块(file1 的内容)

grep 从 file2 中精确提取行块(file1 的内容)

我有两个文件,file1并且file2.

样本内容为file1

A B
C D
E F
G H

的内容file2是这样的:

A B
few other lines
E F
few more other lines
A B
C D
E F
G H
few more other lines
G H

所以我只想搜索整个file1内容块file2。这意味着输出应该只包含这些行:

A B
C D
E F
G H

请注意:- 只有组合在一起的行才应该是输出的一部分。

答案1

grep当涉及到多行模式时,这是相当愚蠢的,但是在比较它们之前,将\n模式和文本的所有换行符转换为 NUL 字符来搜索可以\0解决这个问题。显然还需要\0将输出翻译回。\n

这是您的命令,假设file1包含您要搜索的模式file2

grep -aof <(tr '\n' '\0' < file1) <(tr '\n' '\0' < file2) | tr '\0' '\n'

给定文件的示例输出:

A B
C D
E F
G H

解释:

  • <(tr '\n' '\0' < file1)创建一个 FIFO/命名管道/临时文件类对象,该对象等于file1,但所有换行符都转换为 NUL 字符。
  • <(tr '\n' '\0' < file2)做同样的事情,但是对于file2.
  • grep -f PATTERN_FILE INPUT_FILEPATTERN_FILE从中搜索模式INPUT_FILE
  • 标志-a启用grep二进制文件匹配。这是必需的,因为否则它将跳过包含不可打印字符(例如\0.
  • -o的标志使其grep仅打印匹配的序列,而不是找到它的整行。
  • | tr '\0' '\n'将左侧命令输出中的所有 NUL 字符转换回换行符。

答案2

下面的代码很笨拙,但是可以与 GNU 一起使用awk

awk -v RS="$(<file1)" '{print RT}' file2

答案3

只是为了纯粹的 bash 的乐趣

mapfile -t <file1
while read line ; do
    [ "$line" = "${MAPFILE[i++]}" ] || { ["$line" = "$MAPFILE" ] && i=1 || i=0; }
    [ $i -eq ${#MAPFILE[*]} ] && { printf "%s\n" "${MAPFILE[@]}"; i=0; }
done <file2

答案4

我不太确定您想要的输出是什么,但是使用不完全面向行的语言很容易做到(特别是如果两个文件都可以读入内存)。这是一个 python 脚本,它会告诉您有多少个匹配项。

import sys
find = open(sys.argv[1]).read()
hay = open(sys.argv[2]).read()
print("The text occurs", hay.count(find), "times")

您想打印file1匹配的次数吗?将最后一行替换为:

print(find * hay.count(find))

如果您确实想要的话,您可以将所有内容打包到命令行调用或别名中:

python -c 'import sys; print("The text occurs", open(sys.argv[2]).read().count(open(sys.argv[1]).read()), "times")' file1 file2

相关内容