2011-04-20 96 views
2

我需要建立与这些模式匹配的话,一个正则表达式的话:正则表达式来找到分隔字母和数字或不被符号

字母和数字:

A35,35A,B503X,1ABC5

字母和由分隔的数字 “ - ”, “/”, “\”:

AB-10,10-AB,A10-BA,BA-A10等等......

我写这个正则表达式是:

\b[A-Za-z]+(?=[(?<!\-|\\|\/)\d]+)[(?<!\-|\\|\/)\w]+\b|\b[0-9]+(?=[(?<!\-|\\|\/)A-Za-z]+)[(?<!\-|\\|\/)\w]+\b 

它的工作原理部分,但它仅匹配字母或只用符号分隔的数字。 例子:

10-10,开放式办公室等

而且我不想要这个匹配。

我想我的正则表达式是非常重复的,有点难看。 但这是我现在所拥有的。

任何人都可以帮助我吗?

我正在使用java/groovy。

在此先感谢。

+0

在未来你可以玩这个工具,它是我的救星:http://regexpal.com/ – 2011-04-20 14:35:27

+0

什么是你做的,不要有什么区别不想匹配?每组必须包含字母和数字? – 2011-04-20 14:43:47

+0

在这个字符串中:“10 10-10 open office 10B A10 UCS5000 code DV-3000 300-BR”,正则表达式需要匹配这个词:“10B,A10,UCS5000,DV-3000,300-BR”。字母和数字在同一个词中,用符号分隔或不用符号 - ,/,\ – 2011-04-20 14:48:36

回答

6

有趣的挑战。下面是与挑选出的各类“字”正则表达式的Java程序你是后:

import java.util.regex.*; 
public class TEST { 
    public static void main(String[] args) { 
     String s = "A35, 35A, B503X, 1ABC5 " + 
      "AB-10, 10-AB, A10-BA, BA-A10, etc... " + 
      "10-10, open-office, etc."; 
     Pattern regex = Pattern.compile(
      "# Match special word having one letter and one digit (min).\n" + 
      "\\b      # Match first word having\n" + 
      "(?=[-/\\\\A-Za-z]*[0-9]) # at least one number and\n" + 
      "(?=[-/\\\\0-9]*[A-Za-z]) # at least one letter.\n" + 
      "[A-Za-z0-9]+    # Match first part of word.\n" + 
      "(?:      # Optional extra word parts\n" + 
      " [-/\\\\]    # separated by -,/or //\n" + 
      " [A-Za-z0-9]+   # Match extra word part.\n" + 
      ")*      # Zero or more extra word parts.\n" + 
      "\\b      # Start and end on a word boundary", 
      Pattern.COMMENTS); 
     Matcher regexMatcher = regex.matcher(s); 
     while (regexMatcher.find()) { 
      System.out.print(regexMatcher.group() + ", "); 
     } 
    } 
} 

这里是正确的输出:

A35, 35A, B503X, 1ABC5, AB-10, 10-AB, A10-BA, BA-A10,

注意,只有复杂这些“丑陋”的正则表达式是那些没有正确格式化和评论的!

+0

非常好!这正是我需要的!谢谢ridgerunner! – 2011-04-20 17:24:36

+0

真棒! – jalil 2014-12-01 18:19:19

1

只要使用此:

([a-zA-Z]+[-\/\\]?[0-9]+|[0-9]+[-\/\\]?[a-zA-Z]+) 

在Java \\\/应该进行转义:

([a-zA-Z]+[-\\\/\\\\]?[0-9]+|[0-9]+[-\\\/\\\\]?[a-zA-Z]+) 
+0

这个正则表达式只会匹配字母或只有数字。 – 2011-04-20 14:41:59

+0

好的,我编辑了我的答案。 – hsz 2011-04-20 14:51:56

+0

这几乎工作。如果我有这种情况:DV5-500,这个正则表达式只匹配DV5。我会编辑我的问题,以便更清楚地了解可能性。 – 2011-04-20 15:00:47

0

我第一次合格率

(^|\s)(?!\d+[-/\\]?\d+(\s|$))(?![A-Z]+[-/\\]?[A-Z]+(\s|$))([A-Z0-9]+[-/\\]?[A-Z0-9]+)(\s|$) 

很抱歉,但它不是Java的格式(你需要编辑\ \ S等)。此外,您不能使用\b b/c字边界是任何非字母数字和下划线,因此我使用\s和字符串的开始和结束。

这仍然是一个有点生

编辑

第2版,稍微好一点,但可以为性能通过全光照的占有欲量词得到改善。它匹配ABC76AB-323434-F等,但不ABC19\23

((?<=^)|(?<=\s))(?!\d+[-/\\]?\d+(\s|$))(?![A-Z]+[-/\\]?[A-Z]+(\s|$))([A-Z0-9]+[-/\\]?[A-Z0-9]+)((?=$)|(?=\s)) 
0

的条件(OR NOT A)可以被遗漏。所以符号可以被忽略。

for (String word : "10 10-10 open-office 10B A10 UCS5000 code DV-3000 300-BR".split (" ")) 
    if (word.matches ("(.*[A-Za-z].*[0-9])|(.*[0-9].*[A-Za-z].*)")) 
     // do something 

你没有提到-X4,4x-,4-X,-4-x或-4-X,我希望他们都来匹配。

我的表达式看起来只是用于某些东西-a-something-digits-something,其中某些东西可能是alpha,数字或符号,反之亦然:something-alpha-something-digits-something。如果可能发生其他情况,例如!#$〜()[] {}等等,它会变得更长。

测试使用Scala:

scala> for (word <- "10 10-10 open-office 10B A10 UCS5000 code DV-3000 300-BR".split (" ") 
    | if word.matches ("(.*[A-Za-z].*[0-9])|(.*[0-9].*[A-Za-z].*)")) yield word   
res89: Array[java.lang.String] = Array(10B, A10, UCS5000, DV-3000, 300-BR) 

稍加修改过滤匹配:

String s = "A35, 35A, B53X, 1AC5, AB-10, 10-AB, A10-BA, BA-A10, etc. -4x, 4x- -4-x- 10-10, oe-oe, etc"; 
Pattern pattern = java.util.regex.Pattern.compile ("\\b([^ ,]*[A-Za-z][^ ,]*[0-9])[^ ,]*|([^ ,]*[0-9][^ ,]*[A-Za-z][^ ,]*)\\b"); 
matcher = pattern.matcher (s); 
while (matcher.find()) { System.out.print (matcher.group() + "|") } 

但我仍然有一个错误,我不觉得:

A35|35A|B53X|1AC5|AB-10|10-AB|A10-BA|BA-A10|-4x|4x|-4-x| 

4倍应该是4x-,并且-4-x应该是-4-x-。

+0

这是一个有趣的解决方案,但我不能用空格拆分原始字符串(这是我开发的解决方案的一个规则)。谢谢! – 2011-04-20 17:32:25

+0

分裂只是为了测试这个例子。你要求'匹配单词',而不是'提取匹配单词'。 – 2011-04-20 17:38:48

1

不好意思在Python中编写我的解决方案,我不知道用Java编写足够的Java。

pat = re.compile('(?=(?:([A-Z])|[0-9])' ## This part verifies that 
       '[^ ]*'    ## there are at least one 
       '(?(1)\d|[A-Z]))'  ## letter and one digit. 
       '(' 
       '(?:(?<=[ ,])[A-Z0-9]|\A[A-Z0-9])' # start of second group 
       '[A-Z0-9-/\\\\]*' 
       '[A-Z0-9](?= |\Z|,)'    # end of second group 
       ')', 
       re.IGNORECASE) # this group 2 catches the string 

我的解决办法捕捉所述第二组中所希望的字符串:((?:(?<={ ,])[A-Z0-9]|\A[A-Z0-9])[A-Z0-9-/\\\\]*[A-Z0-9](?= |\Z|,))

之前它验证至少一个字母和一个数字至少存在于钓到字符串中的部分:

(?(1)\d|[A-Z])是一个条件的正则表达式,这意味着“如果基团(1)钓到的东西,那么必须有这里有一个数字,否则必须有一个字母”

的基团(1)是([A-Z])(?=(?:([A-Z])|[0-9])

(?:([A-Z])|[0-9])是匹配的信(钓到)OR一个数字非捕获基团,所以它匹配时一封信,该组(1)不是空的

标志re.IGNORECASE允许处理带有上下字母的字符串。

在第二组中,我有义务编写(?:(?<=[ ,])[A-Z0-9]|\A[A-Z0-9]),因为不允许使用非固定长度的lookbehind断言。这部分表示一个字符不能是' - '前面是空白或字符串的头部。

在相反,(?= |\Z[,)手段“后的字符串或逗号或空白”末端。

此正则表达式假设的字符'-''/''\'不能是第一个字符或一个捕获的字符串中的最后一个。这样对吗 ?

import re 

pat = re.compile('(?=(?:([A-Z])|[0-9])' ## (from here) This part verifies that 
       '[^ ]*'     #    there are at least one 
       '(?(1)\d|[A-Z]))'  ## (to here) letter and one digit. 
       '((?:(?<=[ ,])[A-Z0-9]|\A[A-Z0-9])' 
       '[A-Z0-9-/\\\\]*' 
       '[A-Z0-9](?= |\Z|,))', 
       re.IGNORECASE) # this group 2 catches the string 

ch = "ALPHA13 10 ZZ 10-10 U-R open-office ,10B a10 UCS5000 -TR54 code vg4- DV-3000 SEA 300-BR gt4/ui bn\\3K" 

print [ mat.group(2) for mat in pat.finditer(ch) ] 

s = "A35, 35A, B503X,1ABC5 " +\ 
    "AB-10, 10-AB, A10-BA, BA-A10, etc... " +\ 
    "10-10, open-office, etc." 

print [ mat.group(2) for mat in pat.finditer(s) ] 

结果

['ALPHA13', '10B', 'a10', 'UCS5000', 'DV-3000', '300-BR', 'gt4/ui', 'bn\\3K'] 
['A35', '35A', 'B503X', '1ABC5', 'AB-10', '10-AB', 'A10-BA', 'BA-A10'] 
相关问题