Java RegExps의 이스케이프 문자 가이드

1. 개요

Java의 정규식 API 인 java.util.regex 는 패턴 일치에 널리 사용됩니다. 더 많은 것을 알아 보려면이 기사를 따르십시오.

이 기사에서는 정규 표현식을 사용하여 문자를 이스케이프하는 데 초점을 맞추고 Java에서 수행 할 수있는 방법을 보여줍니다.

2. 특수 정규식 문자

Java 정규식 API 문서에 따르면 정규식에는 메타 문자라고도하는 특수 문자 세트가 있습니다.

문자를 특별한 의미로 해석하는 대신있는 그대로 허용하려면 이스케이프해야합니다. 이러한 문자를 이스케이프하면 주어진 정규식과 문자열을 일치시킬 때 일반 문자로 처리됩니다.

일반적으로이 방식으로 이스케이프해야하는 메타 문자는 다음과 같습니다.

입력 문자열 을 정규식으로 표현 된 패턴과 일치시키는 간단한 코드 예제를 살펴 보겠습니다 .

이 테스트는 주어진 입력 문자열에 대해 foof 패턴이 foo 일 때 를 보여줍니다 . ( 점 문자로 끝나는 foo )가 일치 하면 일치가 성공했음을 나타내는 true 값을 반환합니다 .

@Test public void givenRegexWithDot_whenMatchingStr_thenMatches() { String strInput = "foof"; String strRegex = "foo."; assertEquals(true, strInput.matches(strRegex)); }

입력 문자열 에 점 (.) 문자가 없는데 왜 일치가 성공했는지 궁금 할 수 있습니다.

대답은 간단합니다. 점 (.)은 메타 문자입니다. 여기서 점의 특별한 의미는 그 자리에 '모든 문자'가있을 수 있다는 것입니다. 따라서 matcher가 일치 항목을 찾은 방법이 분명합니다.

점 (.) 문자를 고유 한 의미로 취급하고 싶지 않다고 가정 해 보겠습니다. 대신 점 기호로 해석되기를 원합니다. 이것은 이전 예제에서 패턴 foo를 원하지 않음을 의미합니다 . 입력 문자열에 일치하는 항목이 있습니다.

이런 상황을 어떻게 처리할까요? 대답은 : 점 (.) 문자를 이스케이프하여 특별한 의미가 무시되도록해야합니다.

다음 섹션에서 더 자세히 살펴 보겠습니다.

3. 이스케이프 문자

정규 표현식에 대한 Java API 문서에 따르면 특별한 의미를 가진 문자를 이스케이프 할 수있는 두 가지 방법이 있습니다. 즉, 일반 문자로 처리되도록 강제하는 것입니다.

그들이 무엇인지 보자 :

  1. 백 슬래시 (\)를 사용하여 메타 문자 앞에
  2. \ Q\ E 로 메타 문자를 묶습니다.

이것은 앞서 본 예제에서 도트 문자를 이스케이프하려면 도트 문자 앞에 백 슬래시 문자를 넣어야 함을 의미합니다. 또는 \ Q와 \ E 사이에 점 문자를 넣을 수 있습니다.

3.1. 백 슬래시를 사용하여 이스케이프

이것은 정규 표현식에서 메타 문자를 이스케이프하는 데 사용할 수있는 기술 중 하나입니다. 그러나 백 슬래시 문자는 Java String 리터럴에서도 이스케이프 문자라는 것을 알고 있습니다. 따라서 문자 앞에 백 슬래시 문자를 사용할 때 (\ 문자 자체 포함) 백 슬래시 문자를 두 배로 늘려야합니다.

따라서이 예에서는이 테스트에 표시된대로 정규식을 변경해야합니다.

@Test public void givenRegexWithDotEsc_whenMatchingStr_thenNotMatching() { String strInput = "foof"; String strRegex = "foo\\."; assertEquals(false, strInput.matches(strRegex)); }

여기서 점 문자는 이스케이프되므로 matcher는 단순히 점으로 처리하고 점으로 끝나는 패턴을 찾으려고합니다 (예 : foo. ).

이 경우 해당 패턴 에 대한 입력 문자열 에 일치하는 항목이 없기 때문에 false를 반환합니다 .

3.2. \ Q & \ E를 사용하여 탈출

또는 \ Q\ E 를 사용하여 특수 문자를 이스케이프 할 수 있습니다 . \ Q\ E 까지의 모든 문자를 이스케이프해야 함을 나타내고 \ E\ Q 로 시작된 이스케이프를 종료해야 함을 의미합니다 .

이것은 \ Q\ E 사이에있는 모든 것이 이스케이프 된다는 것을 의미합니다 .

여기에 표시된 테스트 에서 String 클래스 의 split () 은 제공된 정규식을 사용하여 일치를 수행합니다.

우리의 요구 사항은 파이프 (|) 문자로 입력 문자열을 단어로 분할하는 것입니다. 따라서 정규식 패턴을 사용하여이를 수행합니다.

파이프 문자는 정규식에서 이스케이프해야하는 메타 문자입니다.

여기서 이스케이프는 \ Q\ E 사이에 파이프 문자를 배치하여 수행됩니다 .

@Test public void givenRegexWithPipeEscaped_whenSplitStr_thenSplits() \\E"; assertEquals(4, strInput.split(strRegex).length); 

4. Pattern.quote (String S) 메서드

java.util.regex.Pattern 클래스 의 Pattern.Quote (String S) 메소드 는 지정된 정규식 패턴 String 을 리터럴 패턴 String 으로 변환합니다 . 이는 입력 문자열의 모든 메타 문자가 일반 문자로 취급 됨을 의미합니다 .

이 방법을 사용하면 사용하는 것보다 더 편리한 대안이 될 것 \ Q & \ E를 가 주어진 랩으로 문자열을 그들과 함께.

이 메서드가 실제로 작동하는지 살펴 보겠습니다.

@Test public void givenRegexWithPipeEscQuoteMeth_whenSplitStr_thenSplits() bar

In this quick test, the Pattern.quote() method is used to escape the given regex pattern and transform it into a String literal. In other words, it escapes all the metacharacters present in the regex pattern for us. It is doing a similar job to \Q & \E.

The pipe character is escaped by the Pattern.quote() method and the split() interprets it as a String literal by which it divides the input.

As we can see, this is a much cleaner approach and also the developers do not have to remember all the escape sequences.

We should note that Pattern.quote encloses the whole block with a single escape sequence. If we wanted to escape characters individually, we would need to use a token replacement algorithm.

5. Additional Examples

Let's look at how the replaceAll() method of java.util.regex.Matcher works.

If we need to replace all occurrences of a given character String with another, we can use this method by passing a regular expression to it.

Imagine we have an input with multiple occurrences of the $ character. The result we want to get is the same string with the $ character replaced by £.

이 테스트는 $ 패턴 이 이스케이프되지 않고 전달되는 방법을 보여줍니다 .

@Test public void givenRegexWithDollar_whenReplacing_thenNotReplace() { String strInput = "I gave $50 to my brother." + "He bought candy for $35. Now he has $15 left."; String strRegex = "$"; String strReplacement = "£"; String output = "I gave £50 to my brother." + "He bought candy for £35. Now he has £15 left."; Pattern p = Pattern.compile(strRegex); Matcher m = p.matcher(strInput); assertThat(output, not(equalTo(m.replaceAll(strReplacement)))); }

테스트는 $£ 로 올바르게 대체되지 않는다고 주장합니다 .

이제 정규식 패턴을 이스케이프하면 교체가 올바르게 수행되고 다음 코드 스 니펫에 표시된대로 테스트가 통과됩니다.

@Test public void givenRegexWithDollarEsc_whenReplacing_thenReplace() { String strInput = "I gave $50 to my brother." + "He bought candy for $35. Now he has $15 left."; String strRegex = "\\$"; String strReplacement = "£"; String output = "I gave £50 to my brother." + "He bought candy for £35. Now he has £15 left."; Pattern p = Pattern.compile(strRegex); Matcher m = p.matcher(strInput); assertEquals(output,m.replaceAll(strReplacement)); }

$ 문자 를 이스케이프 하고 패턴을 성공적으로 일치시켜 트릭을 수행하는 여기 \\ $에 유의하십시오 .

6. 결론

이 기사에서는 Java의 정규 표현식에서 문자 이스케이프를 살펴 보았습니다.

정규식을 이스케이프해야하는 이유와이를 달성 할 수있는 다양한 방법에 대해 논의했습니다.

항상 그렇듯이이 기사와 관련된 소스 코드는 GitHub에서 찾을 수 있습니다.