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


11


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


Vim에서이 질문을 다소 다루는 검색에 관한 게시물이있었습니다. 짧은 버전은 "명령 구현에 달려 있습니다"... unix.stackexchange.com/questions/90345/…
Drav Sloan

@DravSloan : 나는 그것이 똑같은지 확실하지 않습니다 .Vim 에서 기본적으로 텍스트 를 검색 하고 정규 표현식 을 검색하려면 이스케이프해야합니다. 그러나이 경우 형식은 s/regex//g이미 정규 표현식 을 예상하고 필요한 텍스트 일 ​​것으로 기대합니다 탈출
Jim

답변:


14

때문이다 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 스크립트를 혼란스럽게 만들지 않으려는 경우에 유용합니다.


1
GNU 적어도 나오지 것을 참고, 당신은으로 확장 regexps '에를 사용 나오지도 알 수 있습니다 -r또는 --regexp-extended명령 줄 옵션을 선택합니다. 과도한 탈출로 sed 스크립트를 혼란스럽게 만들지 않으려는 경우에 유용합니다.
cas

@CraigSanders 감사합니다. 답변을 추가했습니다.
Joseph R.

@CraigSanders, 다른 sed구현 (대부분 BSD를 지원하는 ERE를 지원하는 경우)이 -E대신 사용하는 경향이 있습니다 (왜냐하면 grepGNU 와 같은 옵션이기 때문에 더 의미가 있습니다. GNU가 sed선택한 이유 -r는 저에게 미스터리입니다).
Stéphane Chazelas

그래, 나도 미스터리. -E를 사용하는 것이 더 합리적입니다. GNU grep과 일치하도록 -F, -G 및 -P를 추가하십시오. IMO gawk은 동일한 RE 인수로부터도 이익을 얻거나 적어도 -P.
cas

12

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

정규식은 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유사한 연산자의 경우 \@=또는 예 .\{-}를 들어 다르게 수행했습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.