优化Java标识符的正则表达式。分隔结尾和其他部分的数字

时间:2017-07-24 07:47:47

标签: java regex groovy

我需要读取一个字符串作为有效的Java标识符,并分别得到结尾的数字(如果有的话)和起始部分。

a1 -> a,1
a  -> a,
a123b -> a123b,
ab123 -> ab, 123
a123b456 -> a123b, 456
a123b456c789 -> a123b456c, 789
_a123b456c789 -> _a123b456c, 789

我写了一对我在http://www.regexplanet.com/advanced/java/index.html上测试过的正则表达式,他们看起来工作正常

([a-zA-Z_][a-zA-Z0-9_]*[a-zA-Z_]|[a-zA-Z_])(\d+)$
([a-zA-Z_](?:[a-zA-Z0-9_]*[a-zA-Z_])?)(\d+)$

我怎样才能缩短它们?或者你可以建议另一个正则表达式吗?

我不能为\ w更改[a-zA-Z_],也可以为最后一位数字更改。

(我们正在谈论正确的字符串,在替换之前,在Java / Groovy中用于\\)

2 个答案:

答案 0 :(得分:1)

Incremental Java说:

  
      
  • 每个标识符必须至少包含一个字符。
  •   
  • 必须从以下字符中选择第一个字符:字母,下划线或美元符号。第一个字符不能是数字。
  •   
  • 其余字符(除第一个外)可以来自:字母,数字,下划线或美元符号。换句话说,它可以是任何有效的标识符字符。

      简而言之,标识符是从字母,数字,下划线或美元符号中选择的一个或多个字符。唯一的限制是第一个字符不能是数字。
  •   

Java docs也添加:

  

然而,惯例是始终以字母开头,而不是“$”或“_”。此外,按照惯例,美元符号字符根本不会被使用。

您可以使用这个可用于匹配任何有效变量的字符,并将字符的起始块放入一个组,将所有尾随数字放入另一个组:

^(?!\d)([$\w]+?)(\d*)$

请参阅regex demo

或者只匹配遵循约定的标识符的那个:

^(?![\d_])(\w+?)(\d*)$

请参阅this regex demo

<强>详情:

  • ^ - 字符串开头
  • (?!\d) - 第一个字符不能是数字(如果第一个字符为数字或(?![\d_]),则_将无法匹配)
  • ([$\w]+?) - 第1组:一个或多个字词$字符((\w+?)只匹配字母/数字/ _字符),尽可能少(因为+?懒惰量词)直到第一次出现...
  • (\d*)$ - 第2组:字符串末尾的零个或多个数字($)。

Groovy demo

// Non-convention Java identifier
def res = 'a123b$456_c789' =~ /^(?!\d)([$\w]+?)(\d*)$/
print("${res[0][1]} : ${res[0][2]}") // => a123b$456_c : 789

// Convention Java identifier
def res2 = 'a123b456_c' =~ /^(?!\d)([$\w]+?)(\d*)$/
print("${res2[0][1]} : ${res2[0][2]}")  // => a123b456_c : 

答案 1 :(得分:0)

编辑:我尽量让我的解决方案变得尽可能简单,但我没有考虑到它的长度,所以它是不正确的。看看接受的答案

我相信你可以将它缩短为^([a-zA-Z_][a-zA-Z_\d]*[^\d])(\d*)$ - 匹配所有可能的字符,而不是最后的数字和数字。