[unix] 왜 정규식 문자로 해석되기 위해 sed에서 정규식 문자를 이스케이프해야합니까?


cat sed_data.txt | sed 's/\b[0-9]\{3\}\b/NUMBER/g'
를 들어 정규 표현식을 형성 하려면 문자를 이스케이프 해야합니다 . 이 경우 여러 번 해석하기 위해 중괄호를 피해야했습니다.
왜? 탈출하지 않으면 모든 것이 정규식 문자가 될 것으로 기대했습니다. 즉 반대입니다.



답변

때문이다 sed사용 POSIX BREs Eres의 반대 (기본 정규 표현식) 당신은 아마 펄이나 친구에서 사용하고 있습니다 (정규 표현식 확장).

로부터 sed(1)매뉴얼 페이지

REGULAR EXPRESSIONS
       POSIX.2 BREs should be supported, but they aren't completely because of
       performance problems.  The \n sequence in a regular expression  matches
       the newline character, and similarly for \a, \t, and other sequences.

위 링크에서 관련 인용문 :

기본 정규 표현식 또는 BRE 플레이버는 기존 UNIX grep 명령에서 사용되는 플레이버와 유사한 플레이버를 표준화합니다. 이것은 오늘날에도 여전히 사용되는 가장 오래된 정규식 맛입니다. 이 특징을 구별하는 한 가지는 대부분의 메타 문자에 메타 문자의 풍미를주기 위해 백 슬래시가 필요하다는 것입니다. POSIX ERE를 포함한 대부분의 다른 특징은 백 슬래시를 사용하여 메타 문자의 의미를 억제합니다.

크레이그 샌더스의 의견 에서 인용 된 그대로 :

GNU sed에서 최소한 sed에게 -r 또는 –regexp-extended 명령 행 옵션과 함께 확장 정규식을 사용하도록 지시 할 수 있습니다. 과도한 탈출로 sed 스크립트를 혼란스럽게 만들지 않으려는 경우에 유용합니다.


답변

그것은 역사적인 이유 때문입니다.

정규식은 ed70 년대 초 유틸리티에서 유닉스에서 처음 소개되었습니다 . 비록이 ed에 기반 qed구현이하여 같은 저자에 의해보다 복잡한 정규 표현식을 이해 ed만을 이해 ^, $, [...], ., *그리고 \위의 모든 탈출.

이제 더 많은 운영자가 필요 해지면 이전 버전과의 호환성을 유지하면서 운영자를 소개 할 수있는 방법을 찾아야했습니다. 스크립트는 사용하는 데 사용되는 경우 s ed로 명령 s/foo() {/foo (var) {/g의 모든 인스턴스 교체 foo() {와를 foo(var) { 하고 당신이 도입 (또는 {연산자를, 그 해당 스크립트를 깰 것이다.

그러나 스크립트는 수행하지 않습니다 s/foo\(\) {/foo\(var\) {/. 왜냐하면 RE 연산자가 아니 었으므로 s/foo() {/foo(var) {/탈출 할 이유가 없었기 때문 (입니다. 따라서 새로운 구문 \(이나 \{연산자를 도입 해도 이전 구문을 사용하여 기존 스크립트를 깨뜨릴 가능성이 없으므로 이전 버전과의 호환성을 깨뜨리지 않습니다.

그래서 그게 끝났습니다. 나중에 \(...\)처음에는 s ed명령이 s/foo\(.\)/\1bar/나중에 같은 작업을 수행하기 위해 추가되었지만 같은 작업은 수행하지 grep '\(.\)\1'않았습니다 \(xx\)*.

(그래서 거의 10 이후 1979 년) UnixV7에서 정규 표현식의 새로운 형태가 새에 추가되었습니다 egrep하고 awk(그들은 새로운 도구이기 때문에, 깨진 할 이전 버전과의 호환성이 없다) 확장 정규 표현식라는 유틸리티. 마지막으로, 그것은 켄 톰슨의 고대에서 사용할 수있는 기능을 제공 qed(교대 운영자 |그룹화 (..)*)과 같은 몇 가지 연산자를 추가 +하고 ?(하지만 기본적인 정규 표현식의 역 참조 기능을 가지고 있지 않았다).

나중에 BSD의 추가 \<\>(BRE 및 ERE 모두), 및 시스템 V를 추가 \{하고 \}단지 BREs합니다.

그것은 훨씬 나중에 이상까지 아니에요 {}같은 파괴 이전 버전과의 호환성에 의해, ERE에 추가되었습니다. 모두가 그것을 추가 한 것은 아닙니다. 예를 들어, awk버전 4.0.0 (2011)까지의 GNU 는 {POSIX 준수 모드로 강제 실행되지 않는 한 지원하지 않았습니다 .

GNU grep가 90 년대 초에 쓰여졌을 때 , BSD와 SysV의 모든 장점 (예 : \<, {)을 추가했으며 BRE와 ERE에 대해 두 개의 별도 정규식 구문과 엔진을 사용하는 대신 BRE의 BRE에 대해서만 동일한 연산자를 구현했습니다. (, ?, {, +백 슬래시 선행되어야한다 (BRE 다른 구현과 호환되도록). 그것은 당신이 할 수있는 이유 .\+GNU에서 grep(즉, POSIX 아니다 또는 다른 구현에서 지원하지만) 당신이 할 수있는 (.)\1GNU에서 egrep(즉, POSIX 아니다 또는 GNU를 포함하여 많은 다른 구현에서 지원하지만 awk).

\x이전 버전과 호환되는 방식으로 더 많은 연산자를 추가하는 유일한 방법은 연산자를 추가 하지 않습니다. 예를 들어을 perl사용했습니다 (?...). (?=...)ERE에서는 유효하지 않기 때문에 여전히 ERE와 호환됩니다 .*?. vim유사한 연산자의 경우 \@=또는 예 .\{-}를 들어 다르게 수행했습니다 .


답변