2014-06-10 49 views
-2

我只涉足正则表达式,并想知道如果有人可以帮助我做一个Java正则表达式,这与这些特质的字符串匹配:Java的正则表达式:AZ和 - 或者_,但只有一次

  1. 它是1-14个字符长
  2. 它仅包括AZ,az和字母_或 -
  3. 的象征 - 和_必须在一开始
包含一次(一起),而不是

它应该匹配

  • 您好,再次
  • ThisIsValid
  • AlsoThis_

但不

  • -notvalid
  • 不被允许,这
  • 也-This_thing
  • VeryVeryLongStringIndeed

我试过以下的正则表达式字符串

[a-zA-Z^\\-_]+[\\-_]?[a-zA-Z^\\-_]* 

,它似乎工作。但是,我不确定如何使用这种方法来完成字符限制部分。我也试过

[[a-zA-Z]+[\\-_]?[a-zA-Z]*]{1,14} 

但它匹配(例如)它不应该的abc-cde_aa。

+7

这个问题似乎是题外话,因为它确实不显示任何研究或努力虽然说明了理想的必要条件。 – Mena

+0

在这样的问题得到解答的时候,Must've会在糟糕的一天中引起你的注意:http://stackoverflow.com/questions/6078259/regular-expression-to-limit-all-letters-less-than-100-characters – bombax

+1

我已经把它放在你编辑后的重新打开的队列中 - 应该很快回来。我甚至有一个漂亮的答案给你... –

回答

3

这应该工作:

(?![_-])(?!(?:.*[_-]){2,})[A-Za-z_-]{1,14} 

的正则表达式是相当复杂的,让我试着解释它。

  • (?![_-])负向预测。从字符串开头说明第一个字符不是_-。当前位置的负面预览“偷看”并检查它不匹配[_-],它是包含_-的字符组。
  • (?!(?:.*[_-]){2,})另一个负向前瞻,这次匹配​​这是一个non capturing group重复至少两次。该组是.*[_-],它是任何字符,其后是与之前相同的组。所以我们不要想要看到一些字符,其次是_-不止一次。
  • [A-Za-z_-]{1,14}是简单的一点。它只是说组[A-Za-z_-]中的字符在1到14次之间。

该模式的第二部分是最棘手的,但是一个非常常见的伎俩。如果你想看到一个字符A重复在模式的一些点至少X时候,你想看到的模式.*A至少X时间,因为你必须有

zzzzAzzzzAzzzzA.... 

你不在乎还有什么。所以你到达的是(.*A){X,}。现在,你不需要捕捉组群 - 这只会减慢引擎速度。所以我们让这个组不被捕获 - (?:.*A){X,}

你有什么是你只想看一次模式,所以你想而不是找到重复两次或更多次的模式。因此它陷入了负面的前瞻。

这里是一个测试用例:

public static void main(String[] args) { 
    final String pattern = "(?![_-])(?!(?:.*[_-]){2,})[A-Za-z_-]{1,14}"; 
    final String[] tests = { 
      "Hello-Again", 
      "ThisIsValid", 
      "AlsoThis_", 
      "_NotThis_", 
      "-notvalid", 
      "Not-Allow-This", 
      "Nor-This_thing", 
      "VeryVeryLongStringIndeed", 
    }; 
    for (final String test : tests) { 
     System.out.println(test.matches(pattern)); 
    } 
} 

输出:

true 
true 
true 
false 
false 
false 
false 
false 

注意事项:

  1. 字符-是特内里字符组。它必须在一个组的开始或结束,否则它指定范围
  2. lookaround是棘手的,往往是违反直觉。它将检查匹配而不消耗,允许您在相同的数据上测试多个条件。
  3. 重复量词{}非常有用。它有3个州。 {X}正好重复X次。 {X,}至少重复X次。并且{X, Y}XY次之间重复。
+0

完美的是,我有这种感觉,你必须做一些复杂的事情,而事实上负面的预测是我从未见过的。非常感谢! – bombax

3

要检查是否字符串形式XXX-XXX其中-XXX_XXX部分是可选的,你可以使用

[a-zA-Z]+([-_][a-zA-Z]*)? 

这类似于你已经有

[[a-zA-Z]+[\\-_]?[a-zA-Z]*] 

但是你做出关键错误和完全包裹在[...]这使得它的角色类,而这不是你想要的。

要检查匹配的零件是否只有1-14长度,可以使用look-ahead机制。只要将

(?=.{1,14}$) 

在您的正则表达式的开始,以确保部分从比赛直到它结束(由$代表)开始包含任何1-14个字符。

因此,最终的正则表达式可以像

String regex = "(?=.{1,14}$)[a-zA-Z]+([-_][a-zA-Z]*)?"; 

演示

String [] data = { 
    "Hello-Again", 
    "ThisIsValid", 
    "AlsoThis_", 

    "-notvalid", 
    "Not-Allowed-This", 
    "Nor-This_thing", 
    "VeryVeryLongStringIndeed", 
}; 

for (String s : data) 
    System.out.println(s + " : " + s.matches(regex)); 

输出:

Hello-Again : true 
ThisIsValid : true 
AlsoThis_ : true 
-notvalid : false 
Not-Allowed-This : false 
Nor-This_thing : false 
VeryVeryLongStringIndeed : false 
+0

谢谢,有助于理解超前机制。 – bombax

+0

@bombax不客气:) – Pshemo

+1

@bombax你也可以在[这个答案]中找到一些不错的信息(http://stackoverflow.com/questions/3802192/regexp-java-for-password-validation/3802238#3802238)类似的问题。 – Pshemo

相关问题