2009-07-08 8 views
3

간단하지만 쉽게 작동하지는 않습니다.문자열의 일부를 공백으로 대체하는 정규식

'NNDDDDDAAAA'와 같은 문자열이 있는데 'N'은 숫자가 아니며 'D'는 숫자이며 'A'는 아무 것도 아닙니다. 각 A를 공백 문자로 바꿔야합니다. 입력 문자열에있는 'N', 'D'및 'A'의 수는 항상 다릅니다.

나는 두 가지 식으로이를 수행하는 방법을 알고 있습니다. 문자열을 두 개로 분할 한 다음 두 번째 그룹의 모든 내용을 공백으로 바꿀 수 있습니다. 이 같은

하지만 나는 하나의 정규 표현식으로 가능한지 궁금 해서요.

+2

'A'와 다른 것의 차이점은 무엇이라고 생각하십니까? 'A'는 항상 'D'다음에 오는거야? – BryanH

+1

마지막 "D"와 첫 번째 "A"의 차이점은 무엇입니까? "A"그룹이 "D"유형 문자가 아니란 보장이 있습니까? –

+0

Curtis Tasker가 정확합니다. NNDDDD가 항상 N이면 나머지는 아무것도 아닙니다. –

답변

0

나는 당신이 정규식을 요구했는데, 왜 이것에 정규식이 필요한가요? 에 대해 어떻게 :

StringBuilder sb = new StringBuilder(inputString); 
for (int i = sb.length() - 1; i >= 0; i--) { 
    if (Character.isDigit(sb.charAt(i))) 
     break; 
    sb.setCharAt(i, ' '); 
} 
String output = sb.toString(); 

당신은 this post 흥미를 찾을 수 있습니다. 물론 위의 코드에서는 문자열에 적어도 하나의 숫자가 있다고 가정합니다. 마지막 숫자 다음의 모든 문자는 공백으로 변환됩니다. 숫자가 없으면 모든 문자가 공백으로 변환됩니다.

+0

당신이 옳다고 생각합니다. 여러 개의 루프와 indexOf()/substring()이있는 오래된 코드를 리팩터링하고 있으며 간단한 정규식으로 처리 할 수 ​​있다고 생각했습니다. 오래된 논리를 정리할 생각조차하지 않았습니다. 귀하의 접근 방식이이 작업에 가장 효율적이라고 생각합니다. 상자 밖에서 생각해 주셔서 감사합니다. 즉, 초기 요구 사항입니다. –

+0

코드에서 AAA 부분이 숫자가 아닌 것으로 가정합니다. 이것은 문제 설명에 반대되는데, A는 숫자를 포함 할 수있는 '무엇이든지'라고합니다. –

+0

그렇다면 솔루션은 숫자가 아닌 숫자가 오는 지점을 찾기 위해 약간 수정 될 수 있습니다. 그것은 여전히 ​​필요하지 않은 곳에 regexes를 사용하는 것보다 간단 해집니다. –

1

비대칭 vs 무엇을 의미합니까?

[^a-zA-Z0-9]
하지 문자 또는 숫자 모든 것을 일치합니다.

위의 정규식과 일치하는 항목을 공백으로 대체하려고합니다.

이게 당신이 말한 내용입니까?

+0

/[^ a-zA-Z0-9]// g가 아닙니까? – BryanH

+0

"아무것도"일치하는 것을 지울 것이고, 나는 단지 "실제로"일치하는 정규 표현식을 던지기를 원한다. 감사. –

+0

'무엇이든'은 무엇이든, 즉 문자, 숫자, 공백을 의미합니다. 각 발생을 공백으로 바꾸기를 원합니다. 예를 들어, 'AA12345d4 %'는 'AA12345'(끝의 네 칸)로 바뀝니다. –

1

당신은 N과 D를 일치시키기 위해 긍정적 인 시각을 사용하고 싶습니다. 그런 다음 A에 대해 일반적인 일치를 사용하십시오. 자바 문법 뒤에 긍정적 인 모습을 잘하지만, Java regex with look behind에 대한 몇 가지 기사하지

+0

나는 그걸 게시하려하고 있습니다 ... 정직합니다! 예를 들어 (? <= \ D +) –

+0

Java 정규 표현식에 대한 확실하지 않은 경우 : 앞/뒤 제한에 대한 pos/neg 미리보기에 대한 기사를 읽었습니다. regex 엔진의 세 가지 주요 변종과 내가 가지고 있던 주요 테이크 아웃은. NET 정규식이 좋은 물건을 할 수 있지만 가끔은 단지 당신이해야한다는 뜻이 아니기 때문에. –

+0

다음은 다양한 엔진 지원에 대한 멋진 설명입니다. http://www.regular-expressions.info/lookaround.html#limitbehind – laz

3

당신의 묘사, 나는 NNDDDDD 부분 후, 첫 번째 A 실제로 N보다는 A 될 것이라고 믿고있어 감안할 때 그렇지 않으면 DDDDDAAAA 부분 사이에 단색 경계가 없기 때문입니다.

문자열이 실제로 NNDDDDDNAAA 인 것처럼 보이며 NAAA 부분을 공백으로 바꿔야합니다. 이것을 감안할 때 정규 표현식은 다음과 같이 재 작성 될 수 있습니다. (\\D+\\d+)(\\D.+)

Java의 확실한 lookbehind에는 고정 길이 패턴이 필요합니다. + 또는 * 패턴을 사용할 수 없습니다. 대신 중괄호를 사용하고 최대 길이를 지정할 수 있습니다. 예를 들어, 각 + 대신에 {1,9}을 사용할 수 있으며, 1 ~ 9 문자와 일치합니다 (?<=\\D{1,9}\\d{1,9})(\\D.+)

여기에 유일한 문제는 당신이 그렇게됩니다 "NNNDDDDNAAA".replaceAll("(?<=\\D{1,9}\\d{1,9})(\\D.+)", " ")를 사용하여 단일 경기로 NAAA 순서와 일치하고있다 전체 NAAA 시퀀스를 여러 공백이 아닌 단일 공백으로 대체하십시오.

일치 항목의 시작 구분 기호와 문자열 길이를 사용하여 올바른 공백 수를 추가 할 수 있지만 그 지점은 표시되지 않습니다. 나는 당신이 원래의 솔루션으로 더 나아 졌다고 생각합니다. 간단하고 쉽게 따라 할 수 있습니다.

좀 더 빠른 속도를 찾고 있다면 함수 외부에서 패턴을 컴파일하고 StringBuilder 또는 StringBuffer를 사용하여 출력을 생성 할 수 있습니다. 이 모든 NNDDDDDAAAAA 요소에서 큰 String을 작성하는 경우, 추가를 완료 할 때까지 StringBuilder에서 완전히 작업하십시오.

class Test { 

public static Pattern p = Pattern.compile("(\\D+\\d+)(\\D.+)"); 

public static StringBuffer replace(String input) { 
    StringBuffer output = new StringBuffer(); 
    Matcher m = Test.p.matcher(input); 
    if(m.matches()) 
     output.append(m.group(1)).append(m.group(2).replaceAll("."," ")); 

    return output; 
} 

public static void main(String[] args) { 
    String input = args[0]; 
    long startTime; 

    StringBuffer tests = new StringBuffer(); 
    startTime = System.currentTimeMillis(); 
     for(int i = 0; i < 50; i++) 
     { 
      tests.append("Input -> Output: '"); 
      tests.append(input); 
      tests.append("' -> '"); 
      tests.append(Test.replace(input)); 
      tests.append("'\n"); 
     } 
    System.out.println(tests.toString()); 
    System.out.println("\n" + (System.currentTimeMillis()-startTime)); 
} 

} 

는 업데이트 : 나는 빠른 반복적 인 솔루션을 쓰고, 모두를 통해 어떤 임의의 데이터를 달렸다. 반복적 인 솔루션은 약 4-5 배 빠릅니다.

public static StringBuffer replace(String input) 
{ 
    StringBuffer output = new StringBuffer(); 
    boolean second = false, third = false; 
    for(int i = 0; i < input.length(); i++) 
    { 
     if(!second && Character.isDigit(input.charAt(i))) 
      second = true; 

     if(second && !third && Character.isLetter(input.charAt(i))) 
      third = true; 

     if(second && third) 
      output.append(' '); 
     else 
      output.append(input.charAt(i)); 

    } 

    return output; 
} 
관련 문제