Regex 如何编写允许非重复下划线的正则表达式

Regex 如何编写允许非重复下划线的正则表达式,regex,flex-lexer,Regex,Flex Lexer,我正在做一个家庭作业,用Flex创建一个lexer。我必须满足的最后一个要求是: 应修改标识符的定义,以便可以包括下划线,但不允许使用连续下划线、前导下划线和尾随下划线 给定的正则表达式是[A-Za-z][A-Za-z0-9]*。让它识别下划线很容易,我只是将它添加到第二个分组中,如[A-Za-z][A-Za-z0-9.]*。按原样,正则表达式不匹配任何带前导下划线的字符串 在进行尽职调查以确保我没有发布我不需要发布的内容时,我创建了这个正则表达式,它似乎可以工作[A-Za-z]([A-Za-z

我正在做一个家庭作业,用Flex创建一个lexer。我必须满足的最后一个要求是:

应修改标识符的定义,以便可以包括下划线,但不允许使用连续下划线、前导下划线和尾随下划线

给定的正则表达式是
[A-Za-z][A-Za-z0-9]*
。让它识别下划线很容易,我只是将它添加到第二个分组中,如
[A-Za-z][A-Za-z0-9.]*
。按原样,正则表达式不匹配任何带前导下划线的字符串

在进行尽职调查以确保我没有发布我不需要发布的内容时,我创建了这个正则表达式,它似乎可以工作
[A-Za-z]([A-Za-z0-9][]?[A-Za-z0-9])*
。这将在开始处查找字母,然后查找重复模式或字母数字字符、可能的下划线和字母数字字符。虽然这是可行的,但我不认为这是人们所期望的,我希望能从中得到一些更好的建议

我一直在使用以下字符串(由讲师提供)进行测试:


要扩展您的正则表达式,使其一次只允许一个下划线,而下划线也夹在字符串中,您可以使用此正则表达式

[A-Za-z][A-Za-z0-9]*(_[A-Za-z0-9]+)*
我刚刚添加了
([A-Za-z0-9]+)*
部分,该部分将允许单下划线后跟至少一个字母数字字符,整个字符零次或多次,以仅保留下划线可选


现在你必须注意其他方面,因为我对flex不太熟悉。

在你的
[A-Za-z]([A-Za-z0-9][\uz]?[A-Za-z0-9])*
第一个
[A-Za-z0-9]
可以/必须省略(考虑单字母标识符),从而导致
[A-Za-z]([\uz]?[A-Za-z0-9])*
。这似乎正是我们要问的问题,而且似乎是研究在正则表达式中重复组合可选元素的效果的一个很好的练习。

在讨论这个问题时,让我们从以下内容开始:

^    [A-Z][A-Z\d_]+    $
现在,我们想说,我们需要确保字符串中不会出现两个连续的下划线。通常我们要做的是将其包含在负面展望中,如下所示:

(?:(?!__).)+
当我们把它插入到表达式中时,我们会得到这样的结果,它允许任何字符,只要不是换行符或双下划线:

^    [A-Z]    (?:(?!__).)+    $
因此,我们可以将点替换为我们在开始时定义的字符类:

^    [A-Z]    (?:(?!__)[A-Z\d_])+    $

编辑:刚刚意识到结尾也不能有下划线。用lookaheads,你可以把它们锁起来

^[A-Z]    (?:    (?!__)    (?!_$)    [A-Z\d_]    )+$
在这里,我为双下划线添加了一个负前瞻,并在末尾为下划线添加了另一个负前瞻


要想做你想做的事,你必须记住几件事:

  • 以字母数字值开始(
    ^
  • 以字母数字值结束(
    $
  • 可选下划线(
    \uux2?
  • 可能有多个下划线,后跟字母数字
    ()*
示例

    ^[A-Za-z]+(_?[A-Za-z0-9]+)*$
在此处测试:


如果需要,您可以将锚点放在一边。

尝试以下附加测试用例:
n_-ame
name
ab
@sln我怀疑您的性能分析是否适用于
flex
@sln我对flex使用的算法有基本的了解,不明白为什么复杂正则表达式比简单正则表达式更快。我还强烈怀疑,无论您使用哪种工具进行基准测试,都不会使用相同的算法。这就是为什么我认为你的数字不适用于flex。为了让您不必相信我的话,我也做了(实际上使用了flex)并发现两个版本的性能相同。@sln请找到一种更具建设性的方式来表达与其他用户的不同意见。与其亲自攻击他们,说他们无知,不如用反证来反驳他们的说法。关注技术方面,而不是人。我删除了你之前的评论,因为它是。为什么你只允许标识符跨越整行?这毫无意义。另外,flex没有用于非捕获组的语法——它首先没有捕获组的概念。除此之外,如果你解释一下你从OP的正则表达式中改变了什么,以及为什么.flex也没有
\b
(依赖其他人的想法而不是你语言的词汇规则也没有意义)。@sepp2k:抱歉,我不知道flex,因此,我的回答仅限于OP想要的内容,即支持单下划线,夹在整个单词中。我不应该在不充分了解flex的情况下提出建议。感谢您在我的帖子中指出我们的问题。谢谢你的时间。你把问题弄得太难了。例如,负前瞻性引入了很多复杂性,这在这里是不需要的。flex也不支持负前瞻性(或非捕获组的语法-所有组在flex中都是非捕获的)。而且,与大多数其他答案一样,将标识符锚定到行的开头和/或结尾是没有意义的。谢谢。这看起来比我做的要好得多,尽管他们有相似的结果。我被困在
[A-Za-z][A-Za-z0-9])*
中,我真的很想工作,但当然没有。我的错误是把它们分组不正确。我很感谢你的帮助。你为什么用分组来表示下划线?
    ^[A-Za-z]+(_?[A-Za-z0-9]+)*$