정규식에서 이스케이프해야하는 모든 특수 문자 목록


108

사용자가 보내려고하는 메시지와 메시지 템플릿을 일치시키는 응용 프로그램을 만들려고합니다. 메시지 일치를 위해 Java 정규식을 사용하고 있습니다. 템플릿 / 메시지에는 특수 문자가 포함될 수 있습니다.

내 정규식이 작동하고 가능한 최대 사례에서 일치하도록 이스케이프해야하는 특수 문자의 전체 목록을 어떻게 얻을 수 있습니까?

Java 정규식에서 모든 특수 문자를 이스케이프하기위한 범용 솔루션이 있습니까?

답변:


94

Pattern 클래스의 javadoc을 볼 수 있습니다. http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html

특별한 의미가 아닌 일반 문자를 원한다면 거기에 나열된 문자를 이스케이프해야합니다.

더 간단한 해결책으로 \ Q와 \ E 사이에 템플릿을 넣을 수 있습니다. 그 사이의 모든 것은 이스케이프 된 것으로 간주됩니다.


43
\ Q와 \ E를 기억하기 어렵다면 대신 Pattern.quote ( "...")를 사용할 수 있습니다.
mkdev

19
난 당신이 실제로 진술 좋겠
알렉산드르 Dubinsky을

왜, @AleksandrDubinsky?
Sorin

55
@Sorin 단순히 오프 사이트 리소스에 연결하는 것이 아니라 답변에 답변을 명시하는 것이 Stack Exchange의 정신 (아니요, 정책?)이기 때문입니다. 게다가 그 페이지에는 명확한 목록이 없습니다. 목록은 여기에서 찾을 수 있습니다. docs.oracle.com/javase/tutorial/essential/regex/literals.html 하지만 어떤 상황에서 발생하는지 설명하지 않고 " 특정 상황에서 위에 나열된 특수 문자가 메타 문자로 처리 되지 않습니다 "라고 표시됩니다. 탈출하려고하면 요컨대,이 질문은 좋은 대답을 할 가치가 있습니다.
Aleksandr Dubinsky 2014-06-26

8
"[ \Q\E] 사이의 모든 것은 이스케이프 된 것으로 간주됩니다." — 다른 \Q의 및 \E'(원래 정규식 내에서 발생할 수 있음)를 제외하고. 따라서 여기에Pattern.quote 제안 된대로 사용 하고 바퀴를 재발 명하지 않는 것이 좋습니다 .
Sasha

92
  • 정규식에서 이스케이프해야하는 Java 문자는 다음과 같습니다.
    \.[]{}()<>*+-=!?^$|
  • 닫는 괄호 ( ]}) 중 두 개는 동일한 유형의 괄호를 연 후에 만 ​​이스케이프하면됩니다.
  • 에서 []-brackets 일부 문자가 (같은 +-) 탈출하지 않고 때로는 일을.

이스케이프하지 않고 해당 문자를 허용하는 방법이 있습니까?
Dominika

1
문자를 이스케이프한다는 것은 문자를 연산자로 해석하는 대신 문자를 허용하는 것을 의미합니다.
Tobi G.

4
Unescaped -within []는 범위를 정의하는 데 사용되기 때문에 항상 작동하지 않을 수 있습니다. 탈출하는 것이 더 안전합니다. 예를 들어 패턴 [-][-)]문자열은 일치 -하지만 [(-)].
Kenston Choi

1
수락 된 답변이 질문에 대한 답변이지만,이 답변은 제가 간단한 목록을 찾고있을 때 더 도움이되었습니다.
올드 닉

-=!반드시 이스케이프 할 필요는 없으며 컨텍스트에 따라 다릅니다. 예를 들어 단일 문자로 상수 정규식으로 작동합니다.
Hawk

29

탈출하려면 Java 1.5 에서 이것을 사용할 수 있습니다 .

Pattern.quote("$test");

당신은 단어를 정확하게 일치시킬 것입니다 $test


이것이 가장 높은 평가를받은 답변이 아닌 이유는 무엇입니까? 이스케이프가 필요한 모든 문자를 나열하는 복잡한 세부 사항에 들어 가지 않고 문제를 해결하며 JDK의 일부입니다. 추가 코드를 작성할 필요가 없습니다! 단순한!
Volksman

17

String Literals / Metacharacters 문서 페이지 에 따르면 다음과 같습니다.

<([{\^-=$!|]})?*+.>

또한 그 목록을 코드의 어딘가에서 참조하는 것이 멋지지만 그게 어디인지 모르겠습니다 ...


11
String escaped = tnk.replaceAll("[\\<\\(\\[\\{\\\\\\^\\-\\=\\$\\!\\|\\]\\}\\)\\?\\*\\+\\.\\>]", "\\\\$0");
marbel82

1
패턴의 javadoc는 이스케이프 구문을 표시하지 않는 알파벳 문자 이전에 백 슬래시를 사용하면 오류가 말한다, 그러나 백 슬래시는 관계없이 문자가 이스케이프 구조의 일부인지 여부의 알파벳이 아닌 문자 이전에 사용할 수있다. 따라서 훨씬 간단한 정규식으로 충분합니다. s.replaceAll("[\\W]", "\\\\$0")여기서는 \W단어가 아닌 문자를 지정합니다.
Joe Bowbeer

6

모든 사람들이 말한 것을 결합하여 RegExp의 특수 문자 목록을 자신의 문자열에 명확하게 나열하고 수천 개의 "\\"를 시각적으로 구문 분석 할 필요가 없도록 다음을 제안합니다. 이것은 나를 위해 꽤 잘 작동하는 것 같습니다.

final String regExSpecialChars = "<([{\\^-=$!|]})?*+.>";
final String regExSpecialCharsRE = regExSpecialChars.replaceAll( ".", "\\\\$0");
final Pattern reCharsREP = Pattern.compile( "[" + regExSpecialCharsRE + "]");

String quoteRegExSpecialChars( String s)
{
    Matcher m = reCharsREP.matcher( s);
    return m.replaceAll( "\\\\$0");
}

5

@Sorin의 Java Pattern 문서 제안에 따르면 이스케이프 할 문자는 최소한 다음과 같습니다.

\.[{(*+?^$|

4
String escaped = regexString.replaceAll("([\\\\\\.\\[\\{\\(\\*\\+\\?\\^\\$\\|])", "\\\\$1");
fracz

2
)또한 이스케이프되어야하며 문자 클래스 내부 또는 외부에 있는지 여부에 따라 이스케이프 할 문자가 더 많을 수 있습니다.이 경우 Pattern.quote문자 클래스 내부와 외부 모두에서 사용하기 위해 문자열을 이스케이프하는 데 상당히 효과적입니다.
nhahtdh 2015-06-16

3

Pattern.quote(String s)의 종류는 당신이 원하는 않습니다. 그러나 그것은 조금 남았습니다. 실제로 개별 문자를 이스케이프하지 않고 문자열을 \Q...\E.

찾고있는 것을 정확히 수행하는 방법은 없지만, 좋은 소식은 Java 정규식에서 모든 특수 문자를 이스케이프하는 것이 실제로 매우 간단하다는 것입니다.

regex.replaceAll("[\\W]", "\\\\$0")

왜 이것이 작동합니까? 글쎄,에 대한 문서는 Pattern반드시 이스케이프 할 필요가없는 비 알파벳 문자를 이스케이프 할 수 있다고 명시합니다.

이스케이프 된 구조를 나타내지 않는 알파벳 문자 앞에 백 슬래시를 사용하는 것은 오류입니다. 정규 표현식 언어에 대한 향후 확장을 위해 예약되어 있습니다. 역 슬래시는 해당 문자가 이스케이프 처리되지 않은 구조의 일부인지 여부에 관계없이 알파벳이 아닌 문자 앞에 사용될 수 있습니다.

예를 ;들어은 정규식의 특수 문자가 아닙니다. 당신이 그것을 벗어날 경우, Pattern여전히 해석하는 것 \;;. 다음은 몇 가지 예입니다.

  • >다음 \>과 같다>
  • [진다 \[의 탈출 형태 인[
  • 8여전히 8입니다.
  • \)진다 \\\)(가)의 형태 인 이스케이프 \(연접.

참고 : 핵심은 문서에서 실제로 "비 단어 "문자 또는 문자 집합 밖에있는 문자를 의미하는 "알파벳이 아닌"의 정의입니다 [a-zA-Z_0-9].


2

동전의 다른 쪽에서는 특수 문자 = allChars-숫자-ABC-앱 컨텍스트의 공백 인 경우 다음과 같은 "비 문자"정규식을 사용해야합니다.

String regepx = "[^\\s\\w]*";

2

대답은 Java에 대한 것이지만 코드는 내가 생각해 낸 Kotlin String 확장에서 쉽게 조정할 수 있습니다 (@brcolow가 제공 한 것에서 조정 됨).

private val escapeChars = charArrayOf(
    '<',
    '(',
    '[',
    '{',
    '\\',
    '^',
    '-',
    '=',
    '$',
    '!',
    '|',
    ']',
    '}',
    ')',
    '?',
    '*',
    '+',
    '.',
    '>'
)

fun String.escapePattern(): String {
    return this.fold("") {
      acc, chr ->
        acc + if (escapeChars.contains(chr)) "\\$chr" else "$chr"
    }
}

fun main() {
    println("(.*)".escapePattern())
}

인쇄물 \(\.\*\)

여기에서 작동 확인 https://pl.kotl.in/h-3mXZkNE


1

Java regex가 사용하는 이스케이프 문자 목록을 가지고 있고 신뢰할 수 있다고 가정하면 (이 문자가 일부 Pattern 클래스 멤버에 노출 된 경우 좋을 것입니다) 실제로 필요한 경우 다음 메서드를 사용하여 문자를 이스케이프 할 수 있습니다.

private static final char[] escapeChars = { '<', '(', '[', '{', '\\', '^', '-', '=', '$', '!', '|', ']', '}', ')', '?', '*', '+', '.', '>' };

private static String regexEscape(char character) {
    for (char escapeChar : escapeChars) {
        if (character == escapeChar) {
            return "\\" + character;
        }
    }
    return String.valueOf(character);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.