grep来自file2的确切行块(file1的内容)


9

我有两个文件,file1file2

的样本内容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

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


我不明白你的问题。如果您只想打印的确切内容file1而没有其他内容,请使用cat file1
通配符

@Wildcard他想查看file2是否包含与file1完全相同的内容。仿佛正在寻找书中的特定章节一样思考
Sergiy Kolodyazhnyy

我投票重新讨论此问题,因为“集合成员”由多行组成(起初我没有发现),这比提议的重复问题的可接受答案所处理的单行稍微复杂。
库沙兰丹

1
这与集无关。如果要将此标记为重复,则至少要找到有关多行正则表达式的另一个问题。
Michael Vehrs's

Answers:


11

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_FILE搜索从图案(多个)PATTERN_FILEINPUT_FILE
  • -agrep使二进制文件匹配。这是必需的,因为否则它将跳过包含不可打印字符(如)的文件\0
  • -o标志grep使其仅打印匹配的序列,而不打印找到它的整行。
  • | tr '\0' '\n' 将左侧命令输出中的所有NUL字符转换回换行符。


3

纯粹是为了娱乐而已

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

3

这里有点优雅grep+ perl

$ grep -Pzo "$(perl -pe 's/\n/\\n/g' file1.txt )"  file2.txt                    
A B
C D
E F
G H

但是,有一个大问题。如果中有尾随换行符file1,则该格式将不正确,换句话说:A B\nC D\nE F\nG H\n\n

(特别感谢@terdon提供的perl部分)

正如costas所指出的,一个人可以perl -0pe 's/\n(\n+$)?/\\n/g' 代替其他perl命令来避免在后面的换行符。file1.txt


1
如果有尾随换行符,那不是OP想要找到的perl -0pe 's/\n(\n+$)?/\\n/g'。如果没有-0g正则表达式变质剂是多余的。
Costas

1

我不太确定您想要的输出是什么,但是使用非排他性的语言很容易做到(特别是如果两个文件都可以读入内存)。这是一个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

1
grep -lir 'A B \n D C \n whatever' ./folder_to_search

结果将是所有文本完全匹配的文件


0

这是另一种使用python的方法(已通过进行了测试python3 3.5.2,没有的投诉pylint3 1.5.6):

""" Locate entire file contents contiguous in other file """

import sys
import re
from mmap import mmap, PROT_READ

def memmap(name):
    """ Return memoryview of readonly mmap """
    with open(name, 'rb') as file:
        return memoryview(mmap(file.fileno(), 0, access=PROT_READ))

def finder(needle, haystack):
    """ Return iterator """
    return re.compile(re.escape(needle)).finditer(haystack)

print(tuple(finder(*(memmap(name) for name in sys.argv[1:3]))))

命令行参数via的处理sys.argv绝对是简单的。除了传递给,您还可以对传入finder的两个memoryview对象的返回值做很多其他事情tupleSRE_Match返回的迭代器产生的每个项目finder都有多种方法,其采样在print输出中进行汇总(span例如,,告诉每个匹配项的字节范围)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.