正则表达式:按斜杠分割

7
我有一个包含一些信息的解析树。为了提取我需要的信息,我使用了一段代码,该代码基于斜杠(/)分割字符串,但这不是完美的代码。我在这里解释更多细节:
我之前在另一个项目中使用过这个代码,那时它运行得很完美。但现在我的新数据集的解析树更加复杂,这段代码有时会做出错误的决策。
解析树长这样:
(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. ) ) ) ) ) 

正如您所见,树的叶子是斜杠前面的单词。为了获得这些单词,我之前使用过以下代码:

parse_tree.split("/");

但是在我的新数据中,我看到了这样的实例:

1)(TOP Source/NN http://www.alwatan.com.sa/daily/2007-01-31/first_page/first_page01.htm/X ./. )

由于网站地址的原因,有多个斜杠(在这种情况下,只有最后一个斜杠是单词的分隔符)。

2)(NPB~sister~2~2 Your/PRP$ sister/NN //PUNC: )

其中斜线本身就是一个单词。

你能帮我用一个能够处理这些情况的表达式来替换我当前的简单正则表达式吗?

总之,我需要一个正则表达式,它可以基于正斜杠进行拆分,但必须能够处理两个例外情况: 1)如果有一个网站地址,它必须基于最后一个斜杠进行拆分。 2)如果有两个连续的斜杠,它必须基于第二个斜杠进行拆分(第一个斜杠不应被视为分隔符,而是一个单词)。


你能否尝试澄清一下你的问题?你想按“/”拆分,除非它是网站地址? - Praeterii
你是否可以选择在解析树表示中使用哪个分隔符号?使用例如 § 而不是 / 可能更容易/更易于维护。 - collapsar
@Praeterii 非常感谢您的回复。我在我的问题中添加了一个总结,澄清了我需要什么。 - user1419243
@collapsar 既然解析树已经给出,我就不能改变分隔符了。如果我能这样做,那意味着我已经找到了可以满足我的需求的正则表达式。而且,如果我找到了,就不再需要替换分隔符了。 - user1419243
3个回答

3
我根据这篇文章完成了你的要求:

http://www.rexegg.com/regex-best-trick.html

简要概括一下,总体策略如下:
首先,你需要按照以下格式创建一个正则表达式:
NotThis | NeitherThis | (IWantThis)

接下来,你的捕获组$1将只包含你感兴趣的斜杠,以执行拆分。

然后,您可以使用一些不太可能出现的内容来替换它们,之后在这个替换后的术语中执行拆分。

因此,有了这个策略,这就是代码:

正则表达式:

\\/(?=\\/)|(?:http:\\/\\/)?www[\\w\\.\\/\\-]*(?=\\/)|(\\/)

解释:

这个术语应该是双斜杠与lookAhead(只取第一个斜杠)

\\/(?=\\/)

Neither是一个基本的URL检查术语,具有前瞻性以避免捕获最后一个\/。

(?:http:\\/\\/)?www[\\w\\.\\/\\-]*(?=\\/)

IWantThis这个术语简单来说就是斜线:

(\\/)

在Java代码中,您可以像这样将所有内容组合在一起:
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: ) 

1

你应该能够在正则表达式中使用负向回顾后发断言。为了确定这一点,需要更多的输入样本,但似乎对于你的两种情况都有效:

    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")));

这段文本的英译为:

这将输出:

first case:
(TOP Source,
NN http://www.alwatan.com.sa,
daily,
2007-01-31,
first_page,
first_page01.htm,
X .,
. )


second case
(NPB~sister~2~2 Your,
PRP$ sister,
NN ,
/PUNC: )

0

将匹配项进一步筛选,不要包括下方匹配任何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 //

希望这可以帮到你


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接