Java 要按正斜杠拆分的正则表达式
我有一个包含一些信息的解析树。为了提取所需的信息,我使用了一个基于正斜杠(Java 要按正斜杠拆分的正则表达式,java,regex,Java,Regex,我有一个包含一些信息的解析树。为了提取所需的信息,我使用了一个基于正斜杠(/)拆分字符串的代码,但这不是一个完美的代码。我在这里解释更多细节: 早些时候,我在另一个项目中使用了这段代码,效果非常好。但是现在我的新数据集的解析树更加复杂,代码有时会做出错误的决定 解析树如下所示: (TOP~did~1~1 (S~did~2~2 (NPB~I~1~1 I/PRP ) (VP~did~3~1 did/VBD not/RB (VP~read~2~1 read/VB (NPB~article~2~2 th
/
)拆分字符串的代码,但这不是一个完美的代码。我在这里解释更多细节:
早些时候,我在另一个项目中使用了这段代码,效果非常好。但是现在我的新数据集的解析树更加复杂,代码有时会做出错误的决定
解析树如下所示:
(TOP~did~1~1 (S~did~2~2 (NPB~I~1~1 I/PRP ) (VP~did~3~1 did/VBD not/RB (VP~read~2~1 read/VB (NPB~article~2~2 the/DT article/NN ./PUNC. ) ) ) ) )
Pattern p = Pattern.compile("\\/(?=\\/)|(?:http:\\/\\/)?www[\\w\\.\\/\\-]*(?=\\/)|(\\/)");
Matcher m = p.matcher("(TOP~did~1~1 (S~did~2~2 (NPB~I~1~1 I/PRP ) (VP~did~3~1 did/VBD not/RB (VP~read~2~1 read/VB (NPB~article~2~2 the/DT article/NN ./PUNC. ) ) ) ) )\n(TOP Source/NN http://www.alwatan.com.sa/daily/2007-01-31/first_page/first_page01.htm/X ./. )\n(NPB~sister~2~2 Your/PRP$ sister/NN //PUNC: )");
StringBuffer b= new StringBuffer();
while (m.find()) {
if(m.group(1) != null) m.appendReplacement(b, "Superman");
else m.appendReplacement(b, m.group(0));
}
m.appendTail(b);
String replaced = b.toString();
System.out.println("\n" + "*** Replacements ***");
System.out.println(replaced);
String[] splits = replaced.split("Superman");
System.out.println("\n" + "*** Splits ***");
for (String split : splits) System.out.println(split);
正如你所看到的,树的叶子是前斜杠前面的单词。为了获得这些单词,我以前使用过以下代码:
parse_tree.split("/");
但现在,在我的新数据中,我看到了如下实例:
1) (顶级源代码/NNhttp://www.alwatan.com.sa/daily/2007-01-31/first_page/first_page01.htm/X ./)
由于网站地址而有多个斜杠(在本例中,只有最后一个斜杠是单词的分隔符)
2) (NPB~sister~2~2您的/PRP$sister/NN//PUNC:)
斜杠本身就是一个词
你能帮我用一个能处理这些情况的表达式替换我现在的简单正则表达式吗
总结一下,我需要一个正则表达式,它可以基于正斜杠进行拆分,但它必须能够管理两个异常:
1) 如果有网址,则必须根据最后一个斜杠进行拆分。
2) 如果有两个连续的斜杠,则必须基于第二个斜杠进行拆分(第一个斜杠不能被视为分隔符,它是一个单词)。您应该能够使用带有正则表达式的负数lookback。这需要一个更大的输入样本才能确定,但似乎适用于您的两种情况:
String pattern = "(?<![\\:\\/])\\/";
String s1 = "(TOP Source/NN http://www.alwatan.com.sa/daily/2007-01-31/first_page/first_page01.htm/X ./. )";
List<String> a = (List<String>) Arrays.asList(s1.split(pattern));
System.out.println("first case:");
System.out.println(a.stream().map(i->i.toString()).collect(Collectors.joining(",\n")));
System.out.println("\n");
String s2 = "(NPB~sister~2~2 Your/PRP$ sister/NN //PUNC: )";
a = (List<String>) Arrays.asList(s2.split(pattern));
System.out.println("second case");
System.out.println(a.stream().map(i->i.toString()).collect(Collectors.joining(",\n")));
在本文之后,我实现了您的要求: 总而言之,以下是总体战略: 首先,您需要创建以下格式的正则表达式:
NotThis | NeitherThis | (IWantThis)
之后,您的捕获组$1将只包含您感兴趣的斜杠,以执行拆分
然后,您可以将它们替换为不太可能发生的内容,然后在此替换项中执行拆分
因此,考虑到这一策略,下面是代码:
正则表达式:
\\/(?=\\/)|(?:http:\\/\\/)?www[\\w\\.\\/\\-]*(?=\\/)|(\\/)
说明:
not这个术语是带前瞻的双斜杠(仅取第一斜杠)
也不是,这个术语只是一个基本的url检查,具有前瞻性,不捕获最后一个url\/
(?:http:\\/\\/)?www[\\w\\.\\/\\-]*(?=\\/)
我的意思是:这个术语就是斜杠:
(\\/)
在Java代码中,您可以将这一切放在一起,执行如下操作:
(TOP~did~1~1 (S~did~2~2 (NPB~I~1~1 I/PRP ) (VP~did~3~1 did/VBD not/RB (VP~read~2~1 read/VB (NPB~article~2~2 the/DT article/NN ./PUNC. ) ) ) ) )
Pattern p = Pattern.compile("\\/(?=\\/)|(?:http:\\/\\/)?www[\\w\\.\\/\\-]*(?=\\/)|(\\/)");
Matcher m = p.matcher("(TOP~did~1~1 (S~did~2~2 (NPB~I~1~1 I/PRP ) (VP~did~3~1 did/VBD not/RB (VP~read~2~1 read/VB (NPB~article~2~2 the/DT article/NN ./PUNC. ) ) ) ) )\n(TOP Source/NN http://www.alwatan.com.sa/daily/2007-01-31/first_page/first_page01.htm/X ./. )\n(NPB~sister~2~2 Your/PRP$ sister/NN //PUNC: )");
StringBuffer b= new StringBuffer();
while (m.find()) {
if(m.group(1) != null) m.appendReplacement(b, "Superman");
else m.appendReplacement(b, m.group(0));
}
m.appendTail(b);
String replaced = b.toString();
System.out.println("\n" + "*** Replacements ***");
System.out.println(replaced);
String[] splits = replaced.split("Superman");
System.out.println("\n" + "*** Splits ***");
for (String split : splits) System.out.println(split);
输出:
*** Replacements ***
(TOP~did~1~1 (S~did~2~2 (NPB~I~1~1 ISupermanPRP ) (VP~did~3~1 didSupermanVBD notSupermanRB (VP~read~2~1 readSupermanVB (NPB~article~2~2 theSupermanDT articleSupermanNN .SupermanPUNC. ) ) ) ) )
(TOP SourceSupermanNN http://www.alwatan.com.sa/daily/2007-01-31/first_page/first_page01.htmSupermanX .Superman. )
(NPB~sister~2~2 YourSupermanPRP$ sisterSupermanNN /SupermanPUNC: )
*** Splits ***
(TOP~did~1~1 (S~did~2~2 (NPB~I~1~1 I
PRP ) (VP~did~3~1 did
VBD not
RB (VP~read~2~1 read
VB (NPB~article~2~2 the
DT article
NN .
PUNC. ) ) ) ) )
(TOP Source
NN http://www.alwatan.com.sa/daily/2007-01-31/first_page/first_page01.htm
X .
. )
(NPB~sister~2~2 Your
PRP$ sister
NN /
PUNC: )
进一步筛选您的匹配项,使其不包含下面匹配的正则表达式,该正则表达式匹配任何url http/https/ftp,您可以包含任意多的协议
(?<protocol>http(s)?|ftp)://(?<server>([A-Za-z0-9-]+\.)*(?<basedomain>[A-Za-z0-9-]+\.[A-Za-z0-9]+))+ ((/?)(?<path>(?<dir>[A-Za-z0-9\._\-]+)))*
and then match instances of multiple slashes with (/)+
the'+' here is a greedy match which means it will match as many consecutive slashes as it can whether it be // // or //
(?http(s)?ftp):/(?[A-Za-z0-9-]+\)*(?[A-Za-z0-9-]+\[A-Za-z0-9]+)+(/?)((?[A-Za-z0-9\.-]+))*
然后将多个斜杠的实例与(/)+匹配
这里的“+”是贪婪匹配,这意味着它将匹配尽可能多的连续斜杠,无论它是///还是//
希望这有帮助您能尝试澄清您的问题吗?除非有网站地址,否则您想按“/”拆分?您可以选择在解析树表示中使用哪个分隔符符号吗?使用
§
而不是/
@praetri可能更容易/更易于维护。非常感谢您的回复。我在我的问题中添加了一个摘要,澄清了我需要的内容。@collapsar由于已经给出了解析树,我不能更改分隔符。如果我可以这样做,这意味着我已经找到了正则表达式,它可以满足我的需要。如果我找到了,就没有必要再更换分离器了。