사용자가 보내려고하는 메시지와 메시지 템플릿을 일치시키는 응용 프로그램을 만들려고합니다. 메시지 일치를 위해 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);
}