2013-01-19 2 views
1
public static final String PATTERN = "(?<=(^|,))(([^\",]+)|\"([^\"]*)\")(?=($|,))"; 
public static void main(String[] args) { 
    String line = ",1234,ABC"; 
    Matcher matcher = Pattern.compile(PATTERN).matcher(line); 
    while (matcher.find()) { 
     if (matcher.group(3) != null) { 
      System.out.println(matcher.group(3)); 
     } else { 
      System.out.println(matcher.group(4)); 
     } 
    } 
} 

위의 프로그램을 사용하여 문자열 ",1234,ABC"을 구문 분석했습니다. 다음과 같이 분석 후 나는 3 토큰을 얻어야한다 :자바 1.5에서 정규 표현식이 작동하지 않습니다

  1. 빈 문자열 즉 ""
  2. 1234
  3. ABC

자바 1.6하지만 자바 1.5에서 작동하지 않습니다에 작동하는 것 같다.

정규 표현식은 Java 1.4 이후 Java에 있는데 왜 그런 문제가 있습니까?

+2

왜 ','에 분할하지? – Srinivas

+0

@Kedar : Java 1.5에 대한 지원을 중단해야한다고 생각합니다. 오라클은이를 사용하지 않을 것을 권장합니다. – nhahtdh

답변

1
String line = ",1234,ABC"; 
String[]arr= line.split(","); 
System.out.println("arr.length = " + arr.length); 
for(String s : arr) 
{ 
    System.out.println("s = \"" + s+"\""); 
} 

출력은 다음과 같습니다

arr.length = 3 
s = "" 
s = "1234" 
s = "ABC" 
+0

','로 나누는 것은 정규식이 일치 시키려고하는 모든 경우를 다루지는 않습니다. ', 1234, sdf, "123, kjhdf"에서 3 개의 문자열'1234','sdf', 그리고'123, kjhdf '를 고른다. – nhahtdh

+0

처음에는 같은 솔루션을 사용했지만 @nhahtdh가 지적한 것처럼 일부 경우에는 실패합니다. – Kedar

+0

@nhahtdh가 지적한 경우 구분 기호를 이스케이프 처리해야하며, 큰 따옴표를 사용해야하는 경우 쉼표를 이스케이프해야하는 열 이외의 각 열에 대해 사용해야합니다. – Srinivas

5

이이 업데이트 (32) JRE 1.5 업데이트 (18)와 JRE 1.6 전에 최소한까지, 자바 클래스 라이브러리 (오라클에 인수 Sun의 구현)의 버그 (내가 테스트 한 2 가지 버전).

몇 가지 테스트 후, 긍정적 인 모습 숨김 (?<=pattern) 또한 부정적인 모습 숨김 (?<!pattern)1, 2의 구현에 몇 가지 버그가 있습니다. 아마도 패턴이 다른 너비 인 경우 이 번갈아 가며 역 추적하는 방법과 관련이 있습니다. |, 보이지 않는 비 캡처 그룹 내에 있습니다.

룩백의 항목 순서를 바꿀 때 가끔 이 작동하지만 부록 2에서는 항상 작동하지 않을 수도 있음을 보여줍니다. 이 모양 숨김에서 교대를 추출처럼

지금, 그것은 가능한 솔루션입니다 것으로 보인다. 예를 들어, 전환 번호가 (?<=pat1|pat2|pat3) 인 전환 표시는 (?:(?<=pat1)|(?<=pat2)|(?<=pat3))으로 변환됩니다. 룩백 뒤에 |이 없을 때까지 반복합니다. 아래에서 사용한 테스트 케이스에 대한 올바른 결과를 생성하는 것으로 보입니다.

"(?:^|(?<=,))(?:([^\",]+)|\"([^\"]*)\")(?:$|(?=,))" 

그냥보기 미리에 문제가있는 경우에, 나는 또한 비 캡처로 교체 : 문제의 정규식에 대한 그래서

,이 해결 방법 (원래의 가정이 정확)입니다 결과는 같은 용도로 유지되므로 (테스트는 아직 버그가 있음을 보여 주지만, 경우에 따라 다름). 완전히 확신 할 수는 없지만 적어도 (?<=,)(?=,)에 대해 엔진이 올바르게 작동 할 수 있다고 생각합니다. 나는 또한 포획 그룹의 수를 줄이기 위해 자유를 취한다. 그래서 그들을 다시 말해봐.

  1. 부록 입력 문자열 ",abc,1234" 상기 정규식과 "(?<=^|[,.])""(?<!^|[,.])"으로 시험 하였다. JRE 1.5u18과 JRE 1.6u32의 결과가 다릅니다.양수가이면 뒤 따르기 "(?<=^|[,.])"의 경우 JRE 1.5u18의 출력에서 ​​위치 1의 일치가 누락됩니다 (JRE 1.6u32의 출력과 비교). 대신, JRE 1.5u18의 경우 음수 look-behind "(?<!^|[,.])"에 대한 결과에 위치 1이 표시되고 JRE 1.6u32의 출력에는 포함되지 않습니다.

    그것은이 보완 행동을보고 놀라움의 대부분은 양극과 음극으로보기 숨김 서로 정반대이다, 아니다.

  2. 입력 문자열 ",abc,."과 정규식 "(?<=,abc|[,.])"을 사용한 다른 테스트입니다. 위치 1의 일치 항목은 JRE 1.5u18의 결과 목록에 표시되지 않으며 JRE 1.6u32와 비교됩니다.

    교환 번호가 "(?<=[,.]|,abc)" 인 경우 JRE 1.5u18의 결과에서 위치 4의 일치 항목이 누락됩니다 (JRE 1.6u32와 비교).

  3. 는 다른 폭으로 제한하지만, 내가 테스트 한 경우가되지 않을 수 있습니다.

  4. 나는 문제의 정규식을 할 수는 (?<=(,|^))(?<=(^|,))을 변경, 즉 교대로 ^,를 교환하여 입력 ",1234,ABC,\"sdfsdf,sdf\",sdfskhkf,"에서 작동합니다.

+0

이 답변으로 많은 것을 배웠습니다. – Srinivas

+1

@Srinivas : 글쎄, 실제로 이것은 뭔가 유용한 것보다는 버그 리포트와 비슷해 보입니다. – nhahtdh

+0

자세한 답장을 보내 주셔서 감사합니다.하지만이 솔루션이 항상 작동하지 않는 것처럼 보입니다. – Kedar

관련 문제