사용자가 보내려고하는 메시지와 메시지 템플릿을 일치시키는 응용 프로그램을 만들려고합니다. 메시지 일치를 위해 Java 정규식을 사용하고 있습니다. 템플릿 / 메시지에는 특수 문자가 포함될 수 있습니다.
내 정규식이 작동하고 가능한 최대 사례에서 일치하도록 이스케이프해야하는 특수 문자의 전체 목록을 어떻게 얻을 수 있습니까?
Java 정규식에서 모든 특수 문자를 이스케이프하기위한 범용 솔루션이 있습니까?
사용자가 보내려고하는 메시지와 메시지 템플릿을 일치시키는 응용 프로그램을 만들려고합니다. 메시지 일치를 위해 Java 정규식을 사용하고 있습니다. 템플릿 / 메시지에는 특수 문자가 포함될 수 있습니다.
내 정규식이 작동하고 가능한 최대 사례에서 일치하도록 이스케이프해야하는 특수 문자의 전체 목록을 어떻게 얻을 수 있습니까?
Java 정규식에서 모든 특수 문자를 이스케이프하기위한 범용 솔루션이 있습니까?
답변:
Pattern 클래스의 javadoc을 볼 수 있습니다. http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html
특별한 의미가 아닌 일반 문자를 원한다면 거기에 나열된 문자를 이스케이프해야합니다.
더 간단한 해결책으로 \ Q와 \ E 사이에 템플릿을 넣을 수 있습니다. 그 사이의 모든 것은 이스케이프 된 것으로 간주됩니다.
\Q
와 \E
] 사이의 모든 것은 이스케이프 된 것으로 간주됩니다." — 다른 \Q
의 및 \E
'(원래 정규식 내에서 발생할 수 있음)를 제외하고. 따라서 여기에Pattern.quote
제안 된대로 사용 하고 바퀴를 재발 명하지 않는 것이 좋습니다 .
\.[]{}()<>*+-=!?^$|
]
및 }
) 중 두 개는 동일한 유형의 괄호를 연 후에 만 이스케이프하면됩니다.[]
-brackets 일부 문자가 (같은 +
과 -
) 탈출하지 않고 때로는 일을.-
within []
는 범위를 정의하는 데 사용되기 때문에 항상 작동하지 않을 수 있습니다. 탈출하는 것이 더 안전합니다. 예를 들어 패턴 [-]
과 [-)]
문자열은 일치 -
하지만 [(-)]
.
-=!
반드시 이스케이프 할 필요는 없으며 컨텍스트에 따라 다릅니다. 예를 들어 단일 문자로 상수 정규식으로 작동합니다.
String Literals / Metacharacters 문서 페이지 에 따르면 다음과 같습니다.
<([{\^-=$!|]})?*+.>
또한 그 목록을 코드의 어딘가에서 참조하는 것이 멋지지만 그게 어디인지 모르겠습니다 ...
String escaped = tnk.replaceAll("[\\<\\(\\[\\{\\\\\\^\\-\\=\\$\\!\\|\\]\\}\\)\\?\\*\\+\\.\\>]", "\\\\$0");
s.replaceAll("[\\W]", "\\\\$0")
여기서는 \W
단어가 아닌 문자를 지정합니다.
모든 사람들이 말한 것을 결합하여 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");
}
@Sorin의 Java Pattern 문서 제안에 따르면 이스케이프 할 문자는 최소한 다음과 같습니다.
\.[{(*+?^$|
String escaped = regexString.replaceAll("([\\\\\\.\\[\\{\\(\\*\\+\\?\\^\\$\\|])", "\\\\$1");
)
또한 이스케이프되어야하며 문자 클래스 내부 또는 외부에 있는지 여부에 따라 이스케이프 할 문자가 더 많을 수 있습니다.이 경우 Pattern.quote
문자 클래스 내부와 외부 모두에서 사용하기 위해 문자열을 이스케이프하는 데 상당히 효과적입니다.
Pattern.quote(String s)
의 종류는 당신이 원하는 않습니다. 그러나 그것은 조금 남았습니다. 실제로 개별 문자를 이스케이프하지 않고 문자열을 \Q...\E
.
찾고있는 것을 정확히 수행하는 방법은 없지만, 좋은 소식은 Java 정규식에서 모든 특수 문자를 이스케이프하는 것이 실제로 매우 간단하다는 것입니다.
regex.replaceAll("[\\W]", "\\\\$0")
왜 이것이 작동합니까? 글쎄,에 대한 문서는 Pattern
반드시 이스케이프 할 필요가없는 비 알파벳 문자를 이스케이프 할 수 있다고 명시합니다.
이스케이프 된 구조를 나타내지 않는 알파벳 문자 앞에 백 슬래시를 사용하는 것은 오류입니다. 정규 표현식 언어에 대한 향후 확장을 위해 예약되어 있습니다. 역 슬래시는 해당 문자가 이스케이프 처리되지 않은 구조의 일부인지 여부에 관계없이 알파벳이 아닌 문자 앞에 사용될 수 있습니다.
예를 ;
들어은 정규식의 특수 문자가 아닙니다. 당신이 그것을 벗어날 경우, Pattern
여전히 해석하는 것 \;
등 ;
. 다음은 몇 가지 예입니다.
>
다음 \>
과 같다>
[
진다 \[
의 탈출 형태 인[
8
여전히 8
입니다.\)
진다 \\\)
(가)의 형태 인 이스케이프 \
와 (
연접.참고 : 핵심은 문서에서 실제로 "비 단어 "문자 또는 문자 집합 밖에있는 문자를 의미하는 "알파벳이 아닌"의 정의입니다 [a-zA-Z_0-9]
.
대답은 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
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);
}