2013-07-24 4 views
4

다음 결과를 얻으려면 java 정규식을 사용하려는 다음 문자열이 있습니다.Java Regex에서 여러 일치 항목을 캡처하려면

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

성능을 한 번 분석하기 위해 String impelmentation을 분해했습니다. 문자열은 이미 내부적으로 비슷한 것을 수행합니다. 퍼포먼스 겜은 많은 경우에 존재하지 않으며, 다른 것들은 생각보다 훨씬 적습니다. 여기에 요점은 깨끗하고 읽기 쉬운 솔루션을 제시하고 성능이 어디에서나 맞을 수 없다는 것입니다 (프로덕션 코드에서도 성능을 위해 가독성을 확보하기 전에 성능 문제를보고 문서화해야합니다). –

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

그것은이 배열을 얻기 위해,

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())); 
} 

을 또는 그러나, 당신은 쓸 수 있습니다 실제로 정규 표현식을 사용하여이 작업을 수행 할 수 있습니다. 예 :

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]; 
관련 문제