Skip to content

Latest commit

 

History

History
143 lines (89 loc) · 6.61 KB

dotAll-flag-for-regular-expressions.md

File metadata and controls

143 lines (89 loc) · 6.61 KB

정규식의 s(dotAll) flag

상태

본 제안은 the TC39 process 의 4단계에 있습니다.


제안 배경


JS의 정규식에서 마침표(.)는 문자의 종류와는 상관없이 단일 문자와 매칭됩니다. ECMAScript에서는 이 마침표(.)에 두가지 예외사항이 존재합니다.

  1. 마침표(.)는 아스트랄 문자와 매칭되지 않습니다. 이 예외사항을 해결하기 위해서는 u flag를 사용해야합니다.
  2. 마침표(.)는 line terminator characters 와 매칭되지 않습니다.

ECMAScript에서는 아래의 문자를 line terminator characters로 정의하고 있습니다.

  • U+000A LINE FEED (LF) (\n)
  • U+000D CARRIAGE RETURN (CR) (\r)
  • U+2028 LINE SEPARATOR
  • U+2029 PARAGRAPH SEPARATOR

그러나 사용자 정의에 따라 더 많은 문자들이 line terminator characters으로 정의될 수 있습니다. 아래는 그 예시입니다.

  • U+000B VERTICAL TAB (\v)
  • U+000C FORM FEED (\f)
  • U+0085 NEXT LINE

두가지 예외사항로 인해 마침표(.)는 정규식에 있어서 문제를 발생시키게 됩니다.

  • 구현 상, line terminator characters을 모두 포함하지 않기 때문에 사용자에 따라 마침표(.)의 매칭 여부가 달라질 수 있습니다.
  • 일반적으로 마침표(.)는 모든 단일 문자에 대하여 매칭된다는 의미로 사용되지만 실제로는 그렇지 않습니다.

이러한 문제를 해결하기 위해 제안된 s(dotAll) flag에 대해 설명하고자 합니다.

기존의 정규식에서는 line terminator characters를 포함한 모든 단일 문자를 대체하기 위해서 마침표(.)를 사용하지만 제대로 동작하지 않습니다.

/foo.bar/.test('foo\nbar');
// → false

그래서 위의 코드 대신, [\s\S][^]의 특수한 방식으로 구현해야했습니다.

/foo[^]bar/.test('foo\nbar');
// → true

모든 단일 문자와의 매칭은 매우 흔하기 때문에 다른 언어들의 정규식 엔진은 마침표(.)를 line terminator characters를 포함한 모든 단일 문자와 매칭되도록 하는 모드를 제공합니다.

  • 정규식 flag로 DOTALL 또는 SINGLELINE/s를 제공하는 엔진들
  1. JAVAPattern.DOTALL을 제공합니다.
  2. C#과 VBRegexOptions.Singleline을 제공합니다.
  3. Python은 re.DOTALLre.S를 모두 제공합니다.
  • 내장 flag 표현식 (?s)을 제공하는 엔진들
  1. JAVA
  2. C#과 VB
  • 정규 표현식 flag s를 제공하는 엔진들
  1. Perl
  2. PHP

보편적으로, 이름을 s(singleline의 줄임)과 dotAll으로 사용하고 있습니다.

하나의 예외사항으로, Ruby는 the m flag(Regexp::MULTILINE) 를 통해 dotAll 모드를 제공합니다. 안타깝게도 JS에는 m flag가 존재하기 때문에 하위 호환성을 고려하여 이 이름은 사용하지 않았습니다.

제안된 해결책


ECMAScript의 정규식에 마침표(.)와 line terminator characters를 포함한 모든 단일 문자를 매칭하는 s flag를 새로 도입하고자 합니다.

/foo.bar/s.test('foo\nbar');
// → true

상위 API에서의 활용


const re = /foo.bar/s; // Or, `const re = new RegExp('foo.bar', 's');`.
re.test('foo\nbar');
// → true
re.dotAll
// → true
re.flags
// → 's'

FAQ

하위 호환성은 어떤가요?

새롭게 제안된 s flag는 기존과는 다른 로직을 필요로 하기 때문에 기존의 다른 정규식 패턴은 영향을 받지 않습니다.


dotAll 모드는 multiline 모드에 영향을 줄 수 있나요?

이 질문은 s flag가 m/multilineflag의 반대인 singleline모드를 의미하는 것으로 오해하기 때문에 발생하고 있지만 실제로는 그렇지 않습니다. 이 것은 단순히 보편적으로 사용하고 있는 네이밍 방식을 차용하였기 때문에 그렇습니다. 보편적으로 사용되는 이름과는 다른 flag의 이름을 사용하게되면 의미의 혼란을 줄 수 있고, dotAll이라는 이름이 조금 더 명확한 의미를 담고 있기 때문입니다. 이 때문에 이 모드를 singleline 모드 대신 dotAll 모드로 사용하도록 권장하고 있습니다.

dotAllmultiline 두 모드는 독립적으로 동작하기 때문에 함께 사용이 가능합니다. 실제로 multiline은 오직 anchors에만, dotAll는 마침표(.)에만 영향을 줍니다.

만약 dotAllmultiline 두 모드를 사용하게 되면, ^$를 문자열 내의 line terminator characters의 처음과 끝으로 매칭함과 동시에 마침표(.)는 line terminator characters를 포함한 모든 단일 문자에 매칭됩니다.

명세


구현