[size=large]需要匹配的字符串是:[/size]
##$a7a-5064-2460-6$b精装$dCNY26.00$z7-313-1037-0
[size=large]具体要求是:[/size]
1、前两位是两个##、两个数字或者一个#,一个数字。
2、后面的每组字符串都是以$符号开头,$后面是字符、数字下划线、汉字组成的字符串。
3、$a、$b、$d的字符串不可重复,出现次数是0或1次;
$z可重复,出现次数不做限制。
4、$a、$b、$d没有顺序限制。
[size=large] 我写出的正则表达式:[/size]
(^[#0-9]{2})([$a]{2}[\w\d-]+)?([$b]{2}[color=blue].*[/color])?([$d]{2}.*)?([$z]{2}[\w\d-]+)?
[size=large]匹配中出现的问题:[/size]
1、由于上述表达式中蓝色字体的.*能够匹配任意字符,所以如果不写对$d、$z字符串的正则表达式\([$d]{2}.*\)?\([$z]{2}[\\w\\d-]+\)? 也能够匹配到$d、$z的字符串。
2、正则表达式匹配的时候是按照顺序来匹配的。也就是说在正则表达式中$a在$b的前面,如果匹配字符串中没有$a字符串组或者$a字符串组在$b、$d的后面的话,就不能够匹配成功了。针对这个问题我想到的办法是用正则表达式中的“或 |”来组合条件,但是考虑到匹配字符串中以$开头的字符串组比较多,感觉行不通。
[size=large]实现中遇到的难点:[/size]
1、针对由于.*能够匹配任意字符,造成正则表达式中从$d开始,如果不写的话也能够匹配的“$d”和“$z”字符串。应该如何界定$b的结束,从而可以判断出下一组$开头的字符串的开始?
2、如何能够不限定“$a、$b、$d、$z”这些字符串组的顺序,只判断是否在字符串中出现及出现次数?
3、java自带的正则表达式中除了“.”可以匹配汉字之外,还有什么方法能够匹配汉字?
[b][color=red][size=medium] 急用,请各位指点。[/size][/color][/b]
[b]问题补充:[/b]
首先谢谢 congjl2002 (高级程序员) 对我提出问题的解答。对于您的疑问 我在将我的问题补充一下。
首先说明一下上述需要匹配的字符串:
上述字符串对应一个字段号码,每个字段号码对应的字段内容是由多个子字段组成(子字段即:$a7a-5064-2460-6 或者 $dCNY26.00)。$a、$b是子字段标识符。
1、每条字段内容中,子字段标识符(即$a、$b)不定,$a开始到下个$结束是子字段$a对应的子字段内容。具体每条字段中的子字段标识符有哪些,需求中已提供。
2、$后面的内容字母、数字、下划线、“-”、“.”和汉字都有可能出现。例如下面的字段内容中:
1#$20030113d2003####em#y0实用客户英语$b专著$dD634.31-61$9zhao qing tian$f(清)何道生撰$z199?-2001
[b]问题补充:[/b]
我现在想用正则表达式是想两种功能:
1、正向验证。即页面中输入需要匹配的子字段内容后,使用正则表达式验证是否正确。正确将各个子字段合成一个字段内容。
2、逆向解析。即拿到整条字段内容或者多条字段内容时,使用正则表达式验证是否正确。包括该字段中子字段的标识符(即$a $b $d $z)是否正确,及它们的重复性是否正确。
[b]问题补充:[/b]
congjl2002 (高级程序员) 你给我提供的正则表达式是用于javascript中的正则表达式对吧?验证没有问题
刚刚想到一个问题,由于javascript的正则表达式和java自带的正则表达式有些语法稍微有些区别,因此我们可能要写两套正则表达式。javascript中的正则表达式用于正向的验证,java自带的正则表达式用于逆向的解析。java自带的正则表达式逆向解析时主要是有大量数据,也就是多条字段内容时,验证其中一整条字段内容会方便一些。但是现在想一下感觉后台如果自己来写解析的方法,比用正则表达式解析会更方便。这个想法正在商讨中。
我现在还在尝试用java自带的正则表达式来解析字段内容。对于 实现中遇到的难点中的第3条 现在仍然是难点。如果正则表达式中用([$b]{2}.*)? .* 来匹配出现汉字的情况的话,当用([$b]{2}.*)? 来匹配整条字段内容的时候,会将$b开始直到最后所有的字符串都匹配上。不想javascript中可以用\w来匹配汉字 ,不至于把所有字符匹配上。
郁闷啊!!!!!!!
请问有什么方法能够在java自带的正则表达式中准确的匹配出汉字吗?
请指点迷津!
[b]问题补充:[/b]
congjl2002 (高级程序员)
之前没有弄清楚正则表达式在不同的语言之间是否有区别。造成这样的原因是,在开始学习的时候,将教程中的例子在RegexTester 工具中测试正确,放到类中间加上了转义字符结果有时也会有区别;再就是jdk API中提供的java.util.regex.Pattern类中对\w能够匹配字符的说明是 单词字符:[a-zA-Z_0-9] 和你推荐的那篇文章中的说明有所出入(这几天学习正则表达式看的资料就是你提供的那篇文章)。文章中\w 能够匹配的字符是 字母或数字或下划线或汉字 。所以感觉他们之间是有所不同的。
[b]问题补充:[/b]
congjl2002 (高级程序员) 你好
你给我提供的正则表达式 我试过了,在RegexTester工具中测试是好的。但是在java中验证不通过。下面是我写的程序。方便的话测试一下。
public static void main(String[] args) {
String regex = "(^[#0-9]{2})([$a]{2}[\w\d-]+(?!$)?)+([$b]{2}(.?){10}(?!$)?)?([$d]{2}[\w.]*(?!$)?)?([$z]{2}[\w\d-]+(?!$)?)?$";
String matcher = "##$a7a-5064-2460-6$b精装$dCNY26.00$z7-313-1037-0";
find(regex,matcher);
}
/**
* find 方法扫描输入序列以查找与该模式匹配的下一个子序列。
*
* 通过m.find()方法,是按照指定模式与整条字符串进行匹配的 m.groupCount()可以获取指定模式中的分组数 m.group() ==
* m.group(0) 即匹配成功的整条字符串
*
* @param p
* @param m
*/
public static List<String> find(String regex, String matcher) {
List<String> list = new ArrayList<String>();
Pattern p = Pattern.compile(regex);// Pattern(模式类);Pattern类是用来表达和陈述所要搜索模式的对象
Matcher m = p.matcher(matcher);
boolean finded = m.find();
StringBuffer sb = new StringBuffer(); // 该对象用于存储匹配出的字符串,用于下面判断匹配出的内容是否是子字段(即是否包含$)
while (finded) {
for (int i = 0; i <= m.groupCount(); i++) {
// 匹配出的第一个结果是整个字符串
if (i == 0)
continue;
sb.append(m.group(i));
// 匹配出的是指示符 ## 或者 #数字 或者 数字#
if (i == 1 && m.group(i) != null){
list.add(m.group(i));
continue;
}
// 判断匹配出的字符串是否是子字段内容,即是否包含$
if (i != 0 && sb.toString().indexOf("$") == -1)
continue;
sb.delete(0, sb.toString().length());
if(m.group(i) == null) continue;
list.add(m.group(i));
}
finded = m.find();
}
for (int i = 0; i < list.size(); i++) {
System.out.println(i + " " + list.get(i));
}
return list;
}
如果把String regex = "^[\#0-9]{2}(\$[abdz][\w-.]*(?!$)?)+$";
运行程序匹配不出任何东西了。帮忙看看!