我需要构建一个与这些模式匹配的正则表达式:
字母和数字:
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 :(得分: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,
请注意,唯一复杂的“丑陋”的正则表达式是那些没有正确格式化和评论的正则表达式!
答案 1 :(得分:1)
请使用:
([a-zA-Z]+[-\/\\]?[0-9]+|[0-9]+[-\/\\]?[a-zA-Z]+)
在Java中\\
和\/
应该被转义:
([a-zA-Z]+[-\\\/\\\\]?[0-9]+|[0-9]+[-\\\/\\\\]?[a-zA-Z]+)
答案 2 :(得分: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])
是一个非捕获组,匹配一个字母(catched)或一个数字,所以当它与一个字母匹配时,该组(1)不为空
标志re.IGNORECASE允许处理带有大写或小写字母的字符串。
在第二组中,我不得不写(?:(?<=[ ,])[A-Z0-9]|\A[A-Z0-9])
,因为不允许使用非固定长度的后向断言。此部分表示一个不能' - '的字符,前面是空格或字符串的头部。
相反,(?= |\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']
答案 3 :(得分:0)
我的第一次传球得分
(^|\s)(?!\d+[-/\\]?\d+(\s|$))(?![A-Z]+[-/\\]?[A-Z]+(\s|$))([A-Z0-9]+[-/\\]?[A-Z0-9]+)(\s|$)
很抱歉,但它不是java格式化的(你需要编辑\ \ s等)。另外,你不能使用\b
b / c字边界是任何非字母数字和下划线的东西,所以我使用了\s
以及字符串的开头和结尾。
这仍然有点原始
编辑
版本2,略胜一筹,但可以通过占有量量词来提高性能。它与ABC76
AB-32
3434-F
等匹配,但不匹配ABC
或19\23
等。
((?<=^)|(?<=\s))(?!\d+[-/\\]?\d+(\s|$))(?![A-Z]+[-/\\]?[A-Z]+(\s|$))([A-Z0-9]+[-/\\]?[A-Z0-9]+)((?=$)|(?=\s))
答案 4 :(得分:0)
可以省略条件(A 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-,我希望它们都匹配。
我的表达看起来只是某些东西-α-something-digits-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|
4x应为4x-,-4-x应为-4-x-。