我有一个像
这样的文件HEADER foo bar
garbage
SUBHEADER foo foo bar
other garbage
SUBHEADER foo foo bar bar
HEADER foo baz
SUBHEADER foo bar foo foo
SUBHEADER foo foo foo foo
SOMETHING bar bar bar
HEADER baz baz
SUBHEADER baz bar baz foo
大写单词按字面意思出现,并希望找到SOMETHING
以及相应的HEADER
和SUBHEADER
,即
HEADER foo baz
SUBHEADER foo foo foo foo
SOMETHING bar bar bar
它在程序中相当微不足道,但正则表达式可以吗?我可以想象使用否定断言的解决方案,但这变得非常难以理解。
答案 0 :(得分:2)
如果您在SOMETHING之前寻找最近的先前HEADER和SUBHEADER,那么我认为您只需要在您的正则表达式中进行非贪婪匹配 - 假设您有一个一次匹配多行的正则表达式处理器,通常排除grep
,sed
和类似内容。
例如,像这样:
(^HEADER.*?$).*?(^SUBHEADER.*?$).*?(^SOMETHING.*?$)
我还假设'.
'确实匹配换行符(如PCRE_DOTALL
模式),并且'^
'/'$
'将匹配开头/字符串中间的行尾(如PCRE_MULTILINE
模式)。这些是许多正则表达式实现中的可配置选项。
编辑:我已经修改了你在评论中列出的命令,并让它发挥作用。
perl -0777 -ne '/.*(^HEADER.*?\n).*(^SUBHEADER.*?\n).*?(^SOMETHING.*?\n)/ms
and print "$1$2$3*\n"'
(我添加了'm'标志并为偏执狂重新添加了开头的锚点;如果你愿意,可以将它们取回。)
关键的想法是在开头放置一个贪婪的匹配模式,给予正则表达式匹配器权限,以尽可能晚地匹配HEADER。我曾经期待像这样的非锚定的比赛,就像它在开始时有一个隐含的贪婪匹配,但显然存在非贪婪的运算符时,它不会那样工作。