我的问题是Python上this查询的Scala(Java)变体。
特别是,我有一个字符串val myStr = "Shall we meet at, let's say, 8:45 AM?"
。我想将它标记为并保留分隔符(除了空白之外的所有分隔符)。如果我的分隔符只是字符,例如.
,:
,?
等我可以这样做:
val strArr = myStr.split("((\\s+)|(?=[,.;:?])|(?<=\\b[,.;:?]))")
产生
[Shall, we, meet, at, ,, let's, say, ,, 8, :, 45, AM, ?]
但是,我希望将时间签名\\d+:\\d+
作为分隔符,并且仍希望保留它。所以,我想要的是
[Shall, we, meet, at, ,, let's, say, ,, 8:45, AM, ?]
注意:
(?=(\\d+:\\d+))
没有帮助:
本身就是一个分隔符我怎么能做到这一点?
答案 0 :(得分:1)
我建议您匹配所有令牌,而不是拆分字符串,因为这样您可以更好地控制所获得的内容:
\b\d{1,2}:\d{2}\b|[,.;:?]+|(?:(?!\b\d{1,2}:\d{2}\b)[^\s,.;:?])+
请参阅regex demo。
我们开始匹配最具体的模式,最后一个是最通用的模式。
<强>详情
\b\d{1,2}:\d{2}\b
- 1到2位数,:
,包含字边界的2位数字|
- 或[,.;:?]+
- 1个或多个,
,.
,;
,:
,?
字符|
- 或(?:(?!\b\d{1,2}:\d{2}\b)[^\s,.;:?])+
- 匹配任何不是我们的分隔符char或空格([^\s,.;:?]
)的char,它不是时间字符串的起点。考虑this snippet:
val str = "Shall we meet at, let's say, 8:45 AM?"
var rx = """\b\d{1,2}:\d{2}\b|[,.;:?]+|(?:(?!\b\d{1,2}:\d{2}\b)[^\s,.;:?])+""".r
rx findAllIn str foreach println
输出:
Shall
we
meet
at
,
let's
say
,
8:45
AM
?
答案 1 :(得分:-1)
public class StringPatternTokenizer {
Pattern pattern;
public StringPatternTokenizer(String regex) {
this.pattern = Pattern.compile(regex);
}
public void getTokens(String str, NextToken nextToken) {
Matcher matcher = pattern.matcher(str);
int index = 0;
Result result = null;
while (matcher.find()) {
if (matcher.start() > index) {
result = nextToken.visit(null, str.substring(index, matcher.start()));
}
if (result != Result.STOP) {
index = matcher.end();
result = nextToken.visit(matcher, null);
}
if (result == Result.STOP) {
return;
}
}
if (index < str.length()) {
nextToken.visit(null, str.substring(index));
}
}
enum Result {
CONTINUE,
STOP,
}
public interface NextToken {
Result visit(Matcher matcher, String str);
}
/***** test cases FOR IT *****/
public void testCase() {
new StringPatternTokenizer(regex).getTokens(value, (matcher, str) -> {
if (matcher != null) {
System.out.println("part: " + matchStr);
} else {
System.out.println("part(stuff): " + str);
}
return StringPatternTokenizer.Result.CONTINUE;
});
}
}