我相信代码没问题,问题是正则表达式。
基本上我想找一个用户名提示(以@开头),然后我想从给定的单词中提取允许的用户名部分。
例如,如果文本包含" @FOO !!"我只想提取" foo",但我相信问题出在我的" split(" [a-z0-9 -_] +")[0] "部分。
顺便说一句,允许的符号是数字,字母, - 和_
public static Set<String> getMentionedUsers(List<Tweet> tweets) {
Set<String> mentioned = new HashSet<>();
for (Tweet tweet : tweets) {
String tweetToAnal = null;
if (tweet.getText().contains("@")) tweetToAnal = tweet.getText();
if (tweetToAnal == null) continue;
String[] splited = tweetToAnal.split("\\s+");
for (String elem : splited) {
String newElem = "";
if (elem.startsWith("@")) {
newElem = elem.substring(1).toLowerCase().split("[a-z0-9-_]+")[0];
}
if (newElem.length() > 0) mentioned.add(newElem);
}
}
return mentioned;
}
答案 0 :(得分:1)
问题不在你的正则表达式上,而在于你的逻辑。
您正在使用以下行来分析用户名:
if (elem.startsWith("@")) {
newElem = elem.substring(1).toLowerCase().split("[a-z0-9-_]+")[0];
}
如果您逐步调试代码,您会注意到您正在使用substring(1)
@
,然后使用正则表达式进行拆分,因此这种拆分会消耗掉所有人物也是如此。但是,您不希望使用split
方法消费字符,但您只想捕获内容。
因此,您可以通过使用正在使用的否定正则表达式来实际使用split:
split("[^a-z0-9-_]+")
^---- Notice the negate character class indicator
另一方面,您可以将正则表达式与捕获组一起使用,然后获取所需的用户名,而不是将整个文本拆分为多个标记以进行进一步分析。所以,而不是这个代码:
String[] splited = tweetToAnal.split("\\s+");
for (String elem : splited) {
String newElem = "";
if (elem.startsWith("@")) {
newElem = elem.substring(1).toLowerCase().split("[a-z0-9-_]+")[0];
}
if (newElem.length() > 0) mentioned.add(newElem);
您可以使用更简单的代码:
Matcher m = Pattern.compile("(?<=@)([\\w-]+)").matcher(tweetToAnal); // Analyze text with a regex that will capture usernames preceded by @
while (m.find()) { // Stores all username (without @)
mentioned.add(m.group(1));
}
是的,我没有测试代码,所以我可能有一个错字,但你可以理解这个想法。无论如何,代码很容易理解。
答案 1 :(得分:0)
我不是一个Java人员,但你可以很容易地匹配twitter-usernames,而不需要&#34; @&#34;使用以下正则表达式:
(?<=@)[\w-]+
can be seen here。当然你需要正确地转义特殊字符,但由于我不知道Java,你必须自己做这个和实际的匹配。