我有一个以下类型的大文件:
key = asbh
some
lines
of
**text**
key = kafeia
some
more
**text**
and
additionally
more
**text**
and
more
key = lklfh
this
is
another
block
注意(如果重要):“key”行永远不包含感兴趣的字符串(“text”)。
我将以“key”开头的一行与下一行之间的所有行称为块(因此在本例中为 3 个块)。我想返回包含字符串“text”的所有块。 即所需的输出:
key = asbh
some
lines
of
**text**
key = kafeia
some
more
**text**
and
additionally
more
**text**
and
more
我尝试了多种方法,希望我的方向是正确的,但似乎无法让它发挥作用。 这些是我的尝试:
less myfile.txt | sed -n '/key/,/text/p' | less
我相信这可能从它第一次看到“键”开始,然后继续前进(因此返回很多不相关的块),直到它在某处看到“文本”并停止。 这是受到类似问题here的启发,但没有拉动多个块的条件,也没有匹配块内模式的条件。
less myfile.txt | grep -Pzl '(?s)^key([^key]|\n)*text' | less
我认为这可能会更好,如果我能让它工作,我可能会扩展它,因为它当前尝试仅获取键和文本之间的文本(直到下一个键)。
另一条相关说明:我正在使用 Windows 命令行连接到 Linux 服务器并对其进行操作。
为了代码的简洁性和可读性,我建议使用Python或bash脚本文件。
with open('file.txt', 'r') as file:
lines = file.readlines()
blocks = []
current_block = []
for line in lines:
if line.startswith('key'):
# Check if the current block contains 'text'
if any('text' in block_line for block_line in current_block):
blocks.extend(current_block)
current_block = [line]
else:
current_block.append(line)
# Check the last block in case it ends with 'text'
if any('text' in block_line for block_line in current_block):
blocks.extend(current_block)
# Print or use the blocks as needed
for block in blocks:
print(block.strip())
如果你坚持在一行中完成这个操作,你也可以使用这段代码:
awk '/^key/ { if (block ~ /text/) print block; block=""; } { block = block $0 RS } END { if (block ~ /text/) print block }' file.txt
我在几个文件上尝试了这个方法,它是正确的。我希望它对你有用。