我想解析字符串以从中获取字段。字符串的格式(来自数据集)是这样的(->表示选项卡,*表示空格):
Date(yyyymmdd)->Date(yyyymmdd)->*City,*State*-->Description
我只对第一天和该州感兴趣。我尝试过这样的正则表达式:
String txt="19951010 19951011 Red City, WI Description";
String re1="(\\d+)"; // Integer Number 1
String re2=".*?"; // Non-greedy match on filler
String re3="(?:[a-z][a-z]+)"; // Uninteresting: word
String re4=".*?"; // Non-greedy match on filler
String re5="(?:[a-z][a-z]+)"; // Uninteresting: word
String re6=".*?"; // Non-greedy match on filler
String re7="((?:[a-z][a-z]+))"; // Word 1
Pattern p = Pattern.compile(re1+re2+re3+re4+re5+re6+re7,Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Matcher m = p.matcher(txt);
if (m.find())
{
String int1=m.group(1);
String word1=m.group(2);
System.out.print("("+int1.toString()+")"+"("+word1.toString()+")"+"\n");
}
如果城市有两个单词(红色城市),则可以正常工作,然后可以正确提取州,但如果城市只有一个单词,则该城市不起作用。我无法弄清楚,我不需要使用正则表达式,并且愿意接受任何其他建议。谢谢。
问题:
您的问题是当前正则表达式的每个组成部分实际上都与一个数字或[az]词匹配,并用非[az]的任何内容分隔,其中包括逗号。因此,您对于两个字的城市的需求是:
Input:
19951010 19951011 Red City, WI Description
Your components:
String re1="(\\d+)"; // Integer Number 1
String re2=".*?"; // Non-greedy match on filler
String re3="(?:[a-z][a-z]+)"; // Uninteresting: word
String re4=".*?"; // Non-greedy match on filler
String re5="(?:[a-z][a-z]+)"; // Uninteresting: word
String re6=".*?"; // Non-greedy match on filler
String re7="((?:[a-z][a-z]+))"; // Word 1
What they match:
re1: "19951010"
re2: " 19951011 "
re3: "Red" (stops at non-letter, e.g. whitespace)
re4: " "
re5: "City" (stops at non-letter, e.g. the comma)
re6: ", " (stops at word character)
re7: "WI"
但是对于一个单词的城市:
Input:
19951010 19951011 Pittsburgh, PA Description
What they match:
re1: "19951010"
re2: " 19951011 "
re3: "Pittsburgh" (stops at non-letter, e.g. the comma)
re4: ","
re5: "PA" (stops at non-letter, e.g. whitespace)
re6: " " (stops at word character)
re7: "Description" (but you want this to be the state)
您应该做两件事。首先,稍微简化一下正则表达式;指定贪婪vs.勉强等会有点疯狂。只需使用贪婪模式即可。其次,考虑表达规则的最简单方法。
您的规则实际上是:
因此,构建一个遵循该规则的正则表达式。您可以像现在一样通过跳过第二个数字来获得捷径,但是请注意,您确实对以数字开头的城市失去了支持(可能不会发生)。您也不在乎状态。因此,例如:
String re1 = "(\\d+)"; // match first number
String re2 = "[^,]*"; // skip everything thats not a comma
String re3 = ","; // skip the comma
String re4 = "[\\s]*"; // skip whitespace
String re5 = "([a-z]+)"; // match letters (state)
String regex = re1 + re2 + re3 + re4 + re5;
也有其他选择,但是我个人认为正则表达式对于诸如此类的事情非常简单。您可以使用的各种组合split()
,如其他海报所详述。您可以直接使用逗号和空格,indexOf()
然后拉出子字符串。您甚至可以说服aScanner
或也许aStringTokenizer
或StreamTokenizer
为您工作。但是,存在正则表达式可以解决此类问题,并且是完成此工作的好工具。
这是一个示例StringTokenizer
:
StringTokenizer t = new StringTokenizer(txt, " \t");
String date = t.nextToken();
t.nextToken(); // skip second date
t.nextToken(","); // change delimiter to comma and skip city
t.nextToken(" \t"); // back to whitespace and skip comma
String state = t.nextToken();
尽管如此,我仍觉得正则表达式更清晰地表达了规则。
顺便说一句,对于将来的调试,有时仅打印所有捕获组会有所帮助,这可以使您深入了解什么与哪些匹配。一项好的技术是将正则表达式的每个组件临时放在捕获组中,然后全部打印出来。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句