用于标识符的Java正则表达式(字母,数字和下划线)

时间:2016-02-23 13:13:42

标签: java regex string

假设您提供了一个类似于select cast(round(@num/@vat,3) as decimal(18,2)) 的输入。

我想在每个标识符后面添加一个(identifier1 identifier_2 23 4)符号,该标识符可以包含字母,数字和下划线。它们只能以字母开头,后跟字母,数字和下划线的变体。我的方法是这样的:

#

但是,这也会在我想要排除的每个数字后面加上input.replaceAll("[A-Za-z0-9_]+", "$0#"); 个符号。结果应为#。是否有可能用正则表达式来解决这个问题?

2 个答案:

答案 0 :(得分:4)

更新2

Incremental Java说:

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

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

所以,你最好使用

String pattern = "(?:\\b[_a-zA-Z]|\\B\\$)[_$a-zA-Z0-9]*+";

请参阅the regex demo

更新

度Acc。到Representing identifiers using Regular Expression,标识符正则表达式为[_a-zA-Z][_a-zA-Z0-9]*

所以,你可以使用

String pattern = "\\b[_a-zA-Z][_a-zA-Z0-9]*\\b";

注意它允许_______

您可以使用

String p = "\\b_*[a-zA-Z][_a-zA-Z0-9]*\\b";

为了避免这种情况。请参阅IDEONE demo

String s = "(identifier1 identifier_2 23 4) ____ 33"; 
String p = "\\b_*[a-zA-Z][_a-zA-Z0-9]*\\b";
System.out.println(s.replaceAll(p, "$0#"));

输出:(identifier1# identifier_2# 23 4) ____ 33

OLD ANSWER

您可以使用以下模式:

String p = "\\b(?!\\d+\\b)[A-Za-z0-9]+(?:_[A-Za-z0-9]+)*\\b";

或(如果_可以出现在最后):

String p = "\\b(?!\\d+\\b)[A-Za-z0-9]+(?:_[A-Za-z0-9]*)*\\b";

请参阅regex demo

模式要求整个单词(因为表达式用单词边界\b括起来)不应该等于数字(用(?!\d+\b)检查),以及展开的部分{{ 1}}匹配非下划线字符块,后跟零序或多个下划线序列,后跟非下划线字符块。

IDEONE demo

[A-Za-z0-9]+(?:_[A-Za-z0-9])*

输出:String s = "(identifier1 identifier_2 23 4) ____ 33"; String p = "\\b(?!\\d+\\b)[A-Za-z0-9]+(?:_[A-Za-z0-9]*)*\\b"; System.out.println(s.replaceAll(p, "$0#"));

答案 1 :(得分:3)

您当前的正则表达式

  

一个或多个大写或小写字母,数字或下划线,in   无论什么顺序。

根据该正则表达式,54是有效的标识符。

你其实想写

  

一封信,后跟任意数量的字母,数字或   以任何顺序下划线

这将用代码写成:

input.replaceAll("[A-Za-z][A-Za-z0-9_]*", "$0#");

Wiktor指出,此正则表达式仍将匹配不是标识符的内容中的“标识符”。要解决此问题,您可以使用以下变体:

input.replaceAll("\\b([A-Za-z][A-Za-z0-9_]*)\\b", "$1#")

这会拒绝123ab123作为有效标识符,但接受ab123中的123 ab123