Flex 中文字内的多行匹配

Multi-line match inside literals in Flex

我试图在单行或多行中匹配 %[]% 中的文本。我尝试的第一件事是:

\%\[(.*?)\]\%              return MULTILINE_TEXT;

但这仅适用于单行情况,不适用于多行。所以,我想我可以使用 /s:

/\%\[(.*?)\]\%/s           return MULTILINE_TEXT;

但 flex 将此视为无效规则。我最后尝试的是:

\%\[((.*?|\n)*?)\]\%       return MULTILINE_TEXT;

这似乎行得通,但它并没有停在第一个 ]%。在以下示例中:

%[ Some text ...
   Some text ... ]%

... other stuff ...

%[ Some more text ...
   Some more text ... ]%

flex 将 return 整个事物作为一个标记。我能做什么?

请注意,*? 被 flex 视为非贪婪匹配。

Flex 确实支持一些正则表达式标志,但它的语法与大多数正则表达式库略有不同。例如,您可以通过设置 s 标志来改变 . 的含义;更改适用于 括号内的区域(而不是像在 PCRE 中那样遵循标志设置):

"%["(?s:.*)"%]"

比较常见的是看lex兼容的用法:

"%["(.|\n)*"%]"

您还可以使用 x 标志来获得更易读的正则表达式:

(?xs: "%[" .* "%]" )

x 标志在定义中不起作用,仅在模式规则中起作用。)

带引号的字符串(如上)是另一种特定于 (f)lex 的语法,它比反斜杠转义更具可读性,尽管反斜杠转义也有效。但是 flex 没有实现 PCRE/Gnu/JS 扩展,例如 \w\s.

有关 flex 正则表达式的完整指南,请参阅 the flex manual;如果您习惯了其他正则表达式语法,那绝对值得一读。

您可能会感到失望,因为 (f)lex 不支持许多常见的正则表达式扩展,包括非贪婪匹配。这使得为​​由多个字符终止的模式编写模式变得很尴尬,就像您的示例一样。如果分隔符 %[%] 不能嵌套,以至于你真的希望匹配以第一个 %] 结束,你可以使用这样的东西:

%\[([^%]|%+[^]])*%+\]   or  (?x: "%[" ( [^%] | %+ [^]] )* %* "%]" ) 

这有点难以阅读,但它是精确的:%[ 后跟任意次数的非 % 字符或一系列 % 后跟] 以外的其他内容,以 % 后跟 ] 序列结尾。

在上面的模式中,你需要 %+ 而不是 % 来处理像这样的字符串:

%[%% text surrounded by percents%%%]

一个更易读的解决方案也允许嵌套 %[ 是使用 start conditions. There's a complete example of a very similar solution in .