2013-07-24 31 views
4

我有以下字符串,我想用java正则表达式来获得以下结果。Java正则表达式来捕获几个匹配

String s = "/accounts/main/index/page.txt" 
String[] result = {"/accounts/", "/accounts/main/", "/accounts/main/index/"}; 

也就是说,我想获得的父目录层次结构“(这并不一定是一个目录结构)。

注意:字符串“s”是动态分配的,因此它可能是不同级别的目录。

我有以下,但我不确定如何编译将返回我想要的正则表达式。我知道我想要什么只能返回一个结果,最后一个输入数组:

Pattern p = Pattern.compile("^/.+/"); //how do i set up this regex to give me required results. 
    String s = "/accounts/main/index/page.xhtml"; 
    Matcher m = p.matcher(s); 
    while(m.find()){ 
     System.out.println(m.group()); 
    } 

回答

2

线的东西是什么你问的是不可能的;在find的作品中,每场比赛只能在上一场比赛结束后才能比赛。然而,你可以写:

final Pattern p = Pattern.compile("[^/]/"); 
final String s = "/accounts/main/index/page.xhtml"; 
final Matcher m = p.matcher(s); 
while (m.find()) { 
    System.out.println(s.substring(0, m.end())); 
} 

或者得到一个数组:

final Pattern p = Pattern.compile("[^/]/"); 
final String s = "/accounts/main/index/page.xhtml"; 
final Matcher m = p.matcher(s); 
final List<String> resultList = new ArrayList<String>(); 
while (m.find()) { 
    resultList.add(s.substring(0, m.end())); 
} 
final String[] resultArr = resultList.toArray(new String[resultList.size()]); 

(免责声明:没有测试)

+0

嗯,虽然我可以使用团体或类似的东西。但既然这样做是我想要的,我会接受这个作为正确的答案。 – maress

3

我不会使用这个正则表达式。怎么样沿

String[] split = s.split("/"); 

StringBuilder sb = new StringBuilder(s.lastIndexOf('/') + 1); // our result 
sb.append('/'); // initial "/" 

for (int i = 0; i < split.length - 1; i++) { // we don't care about the 
    if (split[i].isEmpty())     // last component 
     continue; 

    sb.append(split[i]); 
    sb.append('/'); 
    System.out.println(sb); // or add to an array/list/etc. 
} 
 
/accounts/ 
/accounts/main/ 
/accounts/main/index/ 
+0

我喜欢这一点,但我希望你没有使用字符串缓冲区,它使这么多的时间越长,不太清楚,真的没有添加任何东西使得解决方案看起来比正则表达式更复杂。不过,+1是为了避免正则表达式做简单的事情。 –

+1

@BillK感谢+1,但我完全不同意。 'StringBuilder'是专门为重复字符串连接/操作而设计的,因为我们可以预先定义它的大小(因为我们知道它会从's'中得到什么),所以它非常适合这种用途。如果我们在这里使用正常字符串(当然,对于更大的输入),那么可能会有明显的性能差异。 – arshajii

+0

我拆开了字符串推理来分析一次性能。字符串已经做了类似的内部。表演中的情绪在许多情况下是不存在的,而在其他情况下,情绪会比你想象的要少得多。最重要的是要提出一个干净可读的解决方案,并且性能不适合任何地方(即使在生产代码中,您应该在交易可读性之前查看并记录性能问题)。 –

1

另一种方式:

Pattern p = Pattern.compile("/[^/]+"); 
String s = "/accounts/main/index/page.xhtml"; 
String dir = ""; 
Matcher m = p.matcher(args[0]); 
while(m.find()){ 
    dir += m.group(); 
    System.out.println(dir + "/"); 
} 
0

这是实际上可以用正则表达式来实现,这将适用于您的示例:

Pattern p = Pattern.compile("^(((/[^/]+/)[^/]+/)[^/]+/)"); 
String s = "/accounts/main/index/page.xhtml"; 
Matcher m = p.matcher(s); 
while (m.find()) 
{ 
    System.out.println(m.group(1)); 
    System.out.println(m.group(2)); 
    System.out.println(m.group(3)); 
} 

不过,你不能有一个正则表达式匹配每一个案例。但是,由于正则表达式的结构已被很好地定义,所以您可以根据目录结构的深度来动态构建它,然后每次编译它。

+0

是的,当我知道我的目录的级别时,这是可以的。我的问题的目的主要是因为我不知道目录的级别有多深。 – maress

+0

@maress哦,我明白了,通过计算'/'字符,你不知道你的目录有多深? – amaurs

0

正则表达式是确定最初分裂,但你必须添加一些代码:

String parts = a.split("(?<!^)(?=/)"); 
for (int i = 0; i < parts.length - 2; i++) 
    parts[i + 1] = parts[i] + parts[i + 1];