String.replaceAll 단일 백 슬래시와 이중 백 슬래시


122

나는 변환하기 위해 노력하고있어 String \something\String \\something\\사용 replaceAll, 그러나 나는 모든 종류의 오류가 계속. 나는 이것이 해결책이라고 생각했습니다.

theString.replaceAll("\\", "\\\\");

그러나 이것은 아래 예외를 제공합니다.

java.util.regex.PatternSyntaxException: Unexpected internal error near index 1

답변:


204

String#replaceAll()A와 인수 해석 정규 표현식 . 은 \에서 탈출 문자 모두 Stringregex. 정규식을 위해 이중 이스케이프해야합니다.

string.replaceAll("\\\\", "\\\\\\\\");

그러나 정확한 문자 단위 교체를 원하고 여기에 패턴이 필요하지 않기 때문에 정규식이 반드시 필요하지는 않습니다. 따라서 String#replace()충분해야합니다.

string.replace("\\", "\\\\");

업데이트 : 주석에 따라 JavaScript 컨텍스트에서 문자열을 사용하려는 것으로 보입니다. StringEscapeUtils#escapeEcmaScript()더 많은 문자를 다루기 위해 대신 사용 하는 것이 좋습니다 .


실제로 소스로 다시 변환해야하는 JavaScript AST에서 사용됩니다. 솔루션이 작동합니다. 감사!
Frank Groeneveld

2
그래도 사용하려면 Matcher # quoteReplacement ()로String#replaceAll() 대체 문자열을 인용 할 수 있습니다 .theString.replaceAll("\\", Matcher.quoteReplacement("\\\\"));
phse

Matcher.quoteReplacement (...)는 좋은 방법입니다! Pshemo의 답변을 참조하십시오!
Hartmut P.

14

이런 종류의 문제를 피하기 위해 (정규 표현식을 취하는 replace) 대신 replaceAll( 일반 문자열을 취하는)를 사용할 수 있습니다 . 여전히 백 슬래시를 이스케이프해야하지만 정규 표현식에 필요한 와일드 방식은 아닙니다.


10

TLDR : theString = theString.replace("\\", "\\\\");대신 사용하십시오.


문제

replaceAll(target, replacement)에는 정규식 (regex) 구문을 사용 target하고 부분적으로 replacement.

문제는 \정규식 ( \d숫자를 나타내는 것처럼 사용할 수 있음 )과 문자열 리터럴 ( "\n"줄 구분 기호를 나타내거나 \"일반적으로 문자열 리터럴의 끝을 나타내는 큰 따옴표 기호를 이스케이프 하는 데 사용할 수 있음)의 특수 문자입니다 .

이 두 경우 모두 \심볼 을 생성하기 위해 심볼 앞에 추가 (예 : 를 통해 문자열 리터럴에서 이스케이프 ) 하여 심볼을 이스케이프 있습니다 (특수 문자 대신 리터럴로 만듭니다 ).\"\"

따라서 target정규식을 표현하려면 \기호를 유지해야하며 \\이러한 텍스트를 나타내는 문자열 리터럴은 다음과 같아야 "\\\\"합니다.

그래서 우리는 \두 번 탈출 했습니다.

  • 정규식에서 한 번 \\
  • 문자열 리터럴에서 한 번 "\\\\"(각각 \으로 "\\"표시됨).

의 경우 replacement \도 특별합니다. 그것은 우리가 다른 특수 문자를 탈출 할 수 있습니다 $통해 $x표기법, 우리는 데이터의 부분은 정규식 일치와 같은 색인 캡처 그룹이 보유 사용할 수 있습니다 x처럼, "012".replaceAll("(\\d)", "$1$1")그룹 1을 포착 각 숫자와 일치합니다, 장소를하고 $1$1두 개의 사본으로 대체됩니다 (복제) 결과 "001122".

다시 말하지만, 리터럴을 replacement표현 \하려면 추가로 이스케이프 처리해야 \합니다.

  • 교체는 두 개의 백 슬래시 문자를 포함해야합니다. \\
  • \\다음과 같이 나타내는 문자열 리터럴"\\\\"

그러나 우리는 두 개의 백 슬래시 replacement를 유지 하기 를 원 하기 때문에 필요합니다 (각각 하나로 표시됨)."\\\\\\\\"\"\\\\"

따라서 버전 replaceAll은 다음과 같이 보일 수 있습니다.

replaceAll("\\\\", "\\\\\\\\");

더 쉬운 방법

아웃하려면 생활 쉽게 자바는 자동으로 텍스트를 탈출 할 수있는 도구 제공 targetreplacement부품. 이제 우리는 문자열에만 집중할 수 있고 정규식 구문은 잊어 버릴 수 있습니다.

replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))

우리의 경우에는

replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))

더 나은

정규식 구문 지원이 실제로 필요하지 않으면 전혀 관여하지 마십시오 replaceAll. 대신 replace. 두 가지 방법 모두 대체합니다 모두 target 들,하지만 replace정규 표현식 구문을 포함하지 않습니다. 그래서 당신은 간단히 쓸 수 있습니다

theString = theString.replace("\\", "\\\\");

7

정규식이므로 첫 번째 인수에서 이스케이프 처리 된 백 슬래시를 이스케이프해야합니다. 대체 (두 번째 인수 -Matcher # replaceAll (String) 참조 )도 백 슬래시의 특별한 의미를 갖기 때문에 다음과 같이 대체해야합니다.

theString.replaceAll("\\\\", "\\\\\\\\");

3

예 ... 정규식 컴파일러가 사용자가 지정한 패턴을 볼 때까지 단일 백 슬래시 만 표시됩니다 (Java의 렉서가 이중 backwhack을 단일 백 슬래시로 전환했기 때문에). 당신은 교체해야 "\\\\"와 함께 "\\\\", 믿거 나 말거나! Java에는 정말 좋은 원시 문자열 구문이 필요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.