我如何才能找到 START_WORD 之前有 3 行的两个单词之间的行sed或者grep或者 ...
例如命令的输出是:
my name is
Mansour
and I confuse to
use sed
or grep for
piping my command output
to get
my ideal output
并且我希望在 START_WORD=command 和 END_WORD=ideal 上使用 sed 或 grep 管道传输命令后退出:
and I confuse to
use sed
or grep for
piping my command output
to get
my ideal output
答案1
你可以做:
grep -Pzo '(?s)\n\K([^\n]*\n){3}[^\n]*command[^\n]*\n.*?\n[^\n]*ideal[^\n]*(?=\n)' file.txt
-P
启用 Perl 兼容正则表达式,-z
使输入数据以 ASCII NUL 分隔,而不是通常的换行符,-o
只获取匹配的部分(?s)
是 DOTALL 修饰符,它使我们能够将换行符 (\n
) 与.
标记匹配\n\K([^\n]*\n){3}
首先匹配\n
然后放弃匹配\K
,([^\n]*\n){3}
匹配包含的行之前的三行command
[^\n]*command[^\n]*\n.*?\n[^\n]*ideal[^\n]*(?=\n)
匹配从具有以下项的行开始command
直到包含以下项的行的所有行ideal
例子:
% cat file.txt
my name is
Mansour
and I confuse to
use sed
or grep for
piping my command output
to get
my ideal output
% grep -Pzo '(?s)\n\K([^\n]*\n){3}[^\n]*command[^\n]*\n.*?\n[^\n]*ideal[^\n]*(?=\n)' file.txt
and I confuse to
use sed
or grep for
piping my command output
to get
my ideal output
答案2
另一种使用 Perl 的方法:
perl -ne 'BEGIN{ my @buffer } unshift(@buffer, $_); splice(@buffer, 4); if(/\bcommand\b/) { print(reverse(@buffer)); while(<>) { print(); /\bideal\b/ && exit } exit }' file
n
:导致 Perl 假设您的程序周围有以下循环,这使得它像 sed -n 或 awk 一样迭代文件名参数:LINE: while (<>) { ... # your program goes here }
-e
:可用于输入一行程序。BEGIN{ my @buffer } unshift(@buffer, $_); splice(@buffer, 4); if(/\bcommand\b/) { print(reverse(@buffer)); while(<>) { print(); /\bideal\b/ && exit } exit }
:将当前行插入到缓冲区的开头,并将缓冲区截断为 4 的长度;如果当前行包含单词command
,则以相反的顺序打印缓冲区并遍历所有剩余的行并打印它们;如果打印的行包含ideal
或已到达文件末尾,则退出。
% cat file
my name is
Mansour
and I confuse to
use sed
or grep for
piping my command output
to get
my ideal output
% perl -ne 'BEGIN{ my @buffer } unshift(@buffer, $_); splice(@buffer, 4); if(/\bcommand\b/) { print(reverse(@buffer)); while(<>) { print(); /\bideal\b/ && exit } exit }' file
and I confuse to
use sed
or grep for
piping my command output
to get
my ideal output
%