我的 data.txt 文件中有以下文本
:MENU1
0. public
1. admin
2. webmail
:SYNTAX
! opt1, ... :
:ERROR1
Error #1, blah... blah.. blah...
Please do ...
:ERROR2
Error #2 ...
我想使用正则表达式(PERL 语法)将部分提取到:MENU1
下一个第一个:
,但从结果中删除MENU1
最后一个。:
一直在尝试几个正则表达式,但在我得到的最接近的解决方案中,我无法使用“贪婪”选项,也无法丢弃最后一个“:”
grep -Poz "^:MENU1\K[\w\W]*:"
这适用于 grep ...
但将所有文本带到最后一个“:”...
我只想直到下一个“:”之后:MENU1
:
0. public
1. admin
2. webmail
(注意最后的空行)
答案1
该模式*:
将匹配所有内容,直到最后一个:
。停在下一个:
你需要的地方*?:
。例如:
% grep -Poz '^:MENU1\K[\w\W]*?:' data.txt
0. public
1. admin
2. webmail
:
您可以通过匹配 . 之前的换行符来删除第一行\K
。例如:
% grep -Poz '^:MENU1\n\K[\w\W]*?:' data.txt
0. public
1. admin
2. webmail
:
要吃空行和:
您可以匹配并丢弃该文本。例如:
% grep -Poz '^:MENU1\n\K[\w\W]*?(?=\n+:)' data.txt
0. public
1. admin
2. webmail
接下来我们可以简化您的角色类,以匹配除以下内容之外的任何内容:
:
% grep -Poz '^:MENU1\n\K[^:]*?(?=\n+:)' data.txt
0. public
1. admin
2. webmail
最后我们可以重写比赛的初始部分:
% grep -Poz '(?<=:MENU1\n)[^:]*?(?=\n+:)' data.txt
0. public
1. admin
2. webmail
这与 @terdon 的想法类似,但是这可以处理空白行,而无需再次调用 grep。
最终的正则表达式利用环视四周断言。这(?<=pattern)
是一个look-behind
断言,可让您匹配pattern
但不将其包含在输出中。这(?=pattern)
是一个look-ahead
断言,让我们可以匹配尾随模式,而不将其包含在输出中。
答案2
关于什么:grep -Poz "^:MENU1\K[^:]*"
?
答案3
@Herbert 的解决方案可能是最简单的,但您也可以使用环视:
$ grep -Poz '(?<=:MENU1\n)[^:]*' file
0. public
1. admin
2. webmail