Regex 如何有效地匹配Perl正则表达式中已经匹配的内容?

Regex 如何有效地匹配Perl正则表达式中已经匹配的内容?,regex,perl,lookahead,lookaround,Regex,Perl,Lookahead,Lookaround,我编写了一个正则表达式来验证必须遵守以下规则的字符串: 必须至少包含一个字符 必须不包含空白字符 第一个字符不能是标点符号 最后一个字母可能不是标点符号 不能以标点符号后跟数字结尾 所有其他字符可以是除/[:@#]以外的任何UTF-8字符 以下是正则表达式: my $name_re = qr/ [^[:punct:][:blank:]] # not punct or blank (?: # followed by..

我编写了一个正则表达式来验证必须遵守以下规则的字符串:

  • 必须至少包含一个字符
  • 必须不包含空白字符
  • 第一个字符不能是标点符号
  • 最后一个字母可能不是标点符号
  • 不能以标点符号后跟数字结尾
  • 所有其他字符可以是除
    /[:@#]
    以外的任何UTF-8字符
  • 以下是正则表达式:

    my $name_re = qr/
         [^[:punct:][:blank:]]      #  not punct or blank
         (?:                        #  followed by...
             [^[:blank:]:@#]*       #      any number non-blank, non-@, non-#, non-@
             [^[:punct:][:blank:]]  #      one not blank or punct
         )?                         #  ... optionally
    /x;
    
    看到少了什么吗?规则#5不强制执行。我一直在通过编写如下代码来实现它:

    die "$proj is not a valid name" unless $proj =~ /\A$name_re\z/
        && $proj !~ /[[:punct:]][[:digit:]]+\z/;
    

    有很多地方我必须这样做,所以我宁愿所有的事情都在一个正则表达式中完成。问题是:怎么做?哪个正则表达式会拒绝诸如“foo,23”之类的值?

    my $name_re = qr/
        \A(?![[:punct:]])         # first character isn't punctuation
        (?:                       # start non-capturing group, repeated once or more
           (?![[:punct:]][[:digit:]]+\z)  # make sure 5th condition isn't violated
           [^[:blank:]:@#]                # match a valid character
        )+                        # end non-capturing group
        (?<![[:punct:]])\z        # last character isn't punctuation
    /x;
    
    my$name\u re=qr/
    \第一个字符不是标点符号
    (?:#启动非捕获组,重复一次或多次
    (?![[:punct:][[:digit:][]+\z)#确保没有违反第5个条件
    [^[:blank::@#]#匹配有效字符
    )+#结束非捕获组
    (?
    
    如果您可以使用可变长度的lookbehind,这将更简单,但我认为Perl不支持它们。

    @f-j的答案对于匹配完整字符串是正确的,但是还需要一个变量,该变量可以作为较大字符串的一部分与其中的其他内容匹配。以下是该版本:

    my $name_re = qr/
        (?![[:punct:]])                # first character isn't punctuation
        (?:                            # start non-capturing group, repeated once or more ...
           (?!                         #    negative look ahead for...
               [[:punct:]]             #       punctuation
               [[:digit:]]+            #       digits
               (?:$|[[:blank:]])       #       eol or blank
           )                           #    ...
           [^[:blank:]:@#]             #     match a valid character
        )+                             # ... end non-capturing group
        (?<![[:punct:]])\b             # last character isn't punctuation
    /x;
    
    my$name\u re=qr/
    (?![:punct:])#第一个字符不是标点符号
    (?:#启动非捕获组,重复一次或多次。。。
    (?!#消极展望。。。
    [:点状:]#标点符号
    [[:位:]+#位
    (?:$|[:blank:])#下线或空白
    )                           #    ...
    [^[:blank::@#]#匹配有效字符
    )+#…结束非捕获组
    
    (?这并不禁止以标点符号加上任何数字结尾的字符串,即
    /[:punct:][:digit:]*/
    。并且向后看的字符串必须是固定宽度的,因此不能使用
    *
    。:-(这会发出“有效”,但应该发出“无效”:
    perl-E'say“foo,23”=~/\a(?![:punct:])(?:(?:(!![:punct:]\d+$)[^[:blank::])+(?@theory-我的“后视”没有重复,我做了一些小的编辑,但它总是检查结尾的标点和数字(我只将
    \d
    切换到
    [:digit://code>,并将“前视”中的
    $
    更改为
    \z
    )@theory-抱歉,我对POSIX字符类的工作方式有点不熟悉,我认为在从
    [:punct:][/code>切换到
    [:punct:][/code>和其他类似更改后,它现在应该可以正常工作了。是的,这会发出“无效的”:
    perl-E'说“foo,23”=~/\a(?[:punct:][digit:][digit:][digit:][digit:][+\z][^[:blank::][+(?