我有两个文件,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_FILE
PATTERN_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