Java 如何将字符串中的中间字符与正则表达式匹配?

Java 如何将字符串中的中间字符与正则表达式匹配?,java,regex,perl,pcre,Java,Regex,Perl,Pcre,在奇数长度的字符串中,如何匹配(或捕获)中间字符 对于PCRE、纯Perl或Java正则表达式,这可能吗 使用.NET正则表达式,您可以轻松地解决它(这可能是一个很好的例子)。所谓纯Perl正则表达式,我的意思是不使用任何像(?{…})这样的代码结构,您可以使用这些结构运行任何代码,当然也可以执行任何操作 字符串可以是任意奇数长度 例如,在字符串12345中,您希望获得3,字符串中心的字符 这是一个关于现代正则表达式风格可能性的问题,而不是关于以其他方式实现这一点的最佳算法。嗯,也许有人可以提出

在奇数长度的字符串中,如何匹配(或捕获)中间字符

对于PCRE、纯Perl或Java正则表达式,这可能吗

使用.NET正则表达式,您可以轻松地解决它(这可能是一个很好的例子)。所谓纯Perl正则表达式,我的意思是不使用任何像
(?{…})
这样的代码结构,您可以使用这些结构运行任何代码,当然也可以执行任何操作

字符串可以是任意奇数长度

例如,在字符串
12345
中,您希望获得
3
,字符串中心的字符


这是一个关于现代正则表达式风格可能性的问题,而不是关于以其他方式实现这一点的最佳算法。

嗯,也许有人可以提出一个纯正则表达式解决方案,但如果没有,您可以始终像这样动态构建正则表达式:

public static void main(String[] args) throws Exception {
    String s = "12345";
    String regex = String.format(".{%d}3.{%d}", s.length() / 2, s.length() / 2);
    Pattern p = Pattern.compile(regex);
    System.out.println(p.matcher(s).matches());
}
使用PCRE和Perl(可能还有Java),您可以使用:

^(?:.(?=.*?(?(1)(?=.\1$))(.\1?$)))*(.)
它将捕获第二个捕获组中奇数长度字符串的中间字符

:


佩尔:是的。使用递归或
/^(.*)(?{.'x length($1)})\z/s
@Oli,这不是真的。使用真正的正则表达式是不可能的,但OP明确表示他知道这一点,并且他正在谈论由某些语言实现的正则表达式引擎。@Qtax,
/…/
是正则表达式匹配运算符。
/
之间的所有内容都是Perl正则表达式。至于递归,我指的是正则表达式递归,而不是Perl递归。@ikegami,你可以在
(?{…})
和friends中嵌入任何你喜欢的代码,做任何事情。我应该删除Perl标记还是说得更清楚一些?如果您想询问PCRE和Java,但不关心Perl,请继续。问现代正则表达式引擎能做什么,而不想知道领导者能做什么,这有点奇怪。我发现:
^(((?=*((?(1)。\1.)$)*\K.
这没什么不同。或者使用正确的量词:
^((?=。+((?(1)。\1.|))$)*\K.
@CasimiretHippolyte,很好的解决方案,+1!你应该把它贴上去。@Casimirithippolyte也许今天就是那天?:)你们很接近,但你们可以通过让这些量词懒洋洋地匹配并给它们一个停下来的地方来消除条件:
^(?:(?=.*(..1?$)+?\K.(?=\1)
@jaytea:你们也很接近,
^ # beginning of the string
(?: # loop
  . # match a single character
  (?=
    # non-greedy lookahead to towards the end of string
    .*?
    # if we already have captured the end of the string (skip the first iteration)
    (?(1)
      # make sure we do not go past the correct position
      (?= .\1$ )
    )
    # capture the end of the string +1 character, adding to \1 every iteration
    ( .\1?$ )
  )
)* # repeat
# the middle character follows, capture it
(.)