为Java标识符优化正则表达式。将结尾和其他部分中的数字分开
我需要读取一个字符串作为有效的Java标识符,并分别获取结尾(如果有)和开始部分的数字为Java标识符优化正则表达式。将结尾和其他部分中的数字分开,java,regex,groovy,Java,Regex,Groovy,我需要读取一个字符串作为有效的Java标识符,并分别获取结尾(如果有)和开始部分的数字 a1 -> a,1 a -> a, a123b -> a123b, ab123 -> ab, 123 a123b456 -> a123b, 456 a123b456c789 -> a123b456c, 789 _a123b456c789 -> _a123b456c, 789 我已经编写了一对正则表达式,并对其进行了测试,它们看起来可以正常工作 ([a-zA-Z_]
a1 -> a,1
a -> a,
a123b -> a123b,
ab123 -> ab, 123
a123b456 -> a123b, 456
a123b456c789 -> a123b456c, 789
_a123b456c789 -> _a123b456c, 789
我已经编写了一对正则表达式,并对其进行了测试,它们看起来可以正常工作
([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中\\for\\replacement之前的正则表达式字符串)
- 每个标识符必须至少有一个字符。
- 第一个字符必须从字母、下划线或美元符号中选取。第一个字符不能是数字。
- 其余字符(除第一个字符外)可以来自:字母、数字、下划线或美元符号。换句话说,它可以是任何有效的标识符字符。
简而言之,标识符是从字母、数字、下划线或美元符号中选择的一个或多个字符。唯一的限制是第一个字符不能是数字
^(?!\d)([$\w]+?)(\d*)$
见
或仅与遵循约定的标识符匹配的:
^(?![\d_])(\w+?)(\d*)$
看
详细信息:
-字符串的开头^
-第一个字符不能是数字((?!\d)
如果第一个字符是数字或(?![\d])
,则匹配将失败)
-第1组:一个或多个单词或([$\w]+?)
字符($
将只匹配字母/数字/(\w+?)
字符),尽可能少(因为。
是惰性量词),直到第一次出现+?
-第2组:字符串末尾的零位或多位((\d*)$
)$
编辑:我试图使我的解决方案尽可能简单,但我没有考虑足够长的时间,所以它是不正确的。看看公认的答案
我相信您可以将其缩短为
^([a-zA-Z_u2;][a-zA-Z_2;d]*[^\d])(\d*)$
-将所有可能的字符与结尾处的数字进行匹配,而不是一个数字 请注意,在Java/Groovy正则表达式中,\w
默认情况下与[a-zA-Z0-9\]
匹配。仅当您传递了Pattern.UNICODE\u CHARACTER\u CLASS
时,\w
模式将匹配所有UNICODE字母和数字。字符串必须是变量名。所以,我不是在搜索所有的Unicode字母和数字。这里没关系。考虑到您的第一篇评论,我得出结论,我们可以影响\\w等缩短模式的工作方式?可以更改速记字符类Unicode行为。而且,您的逻辑是正确的。但是,如果您的意思是一个有效的Java标识符,那么您的正则表达式也应该能够匹配Java标识符中出现的$
。谢谢。我懂了。。。是的,我可以将[a-zA-Z0-9_u2;]更改为\\w,并且我应该在开始处添加^at以检查字符串的开头。但是最后一个“?”有什么用呢?将(\\d+)更改为(\\d*)将完成相同的工作,不是吗?并且不可能使用不同的逻辑吗?你的答案对我来说肯定非常有用,检查字符串的开头,但我有点失望——逻辑上它和我发现的是一样的。我在正则表达式方面是个新手。你所看到的怪物怎么可能是几乎相同的解决方案?@Gangnus不知道你所说的“怪物”是什么意思。你在这个问题上没有提出任何要求,除了帮助你修复代码(通过从你尝试过的模式中推断出要求),我想我自己也无能为力。我的意思是,你在这方面的经验是我的好几倍。没有冒犯的意思,相反。。。至于需求,在问题的开头,它们写在我的正则表达式之前。@Gangnus:这些不是需求,只是一些测试用例。您应该显式地编写有效的Java标识符。^([a-zA-Z\d]*[^\d])(\d*)$
不正确,因为变量名不能以数字开头。是的,我刚刚意识到这一点。编辑以使其正确。(希望)不,[^\d]
表示除数字以外的任何字符。任何。我在你第二次评论之前编辑过。现在我不知道它是否比问题中的还要短,这不是写得短的问题<代码>[^\d]匹配
,*
,Ł
,Щ
。。。
// 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 :