고쳐 쓰다

고쳐 쓰다

grep기본적으로 이들은 sed모두 "기본 정규 표현식"("BRE")을 사용하는 것으로 설명됩니다. BRE는 이를 잘 설명합니다.여기.

그러나 다음 출력을 고려하십시오.

# echo '    aaaaa   ' | grep '\(aaaaa\|bbbbb\)'
    aaaaa
# echo '    aaaaa   ' | sed '/\(aaaaa\|bbbbb\)/ s/ /_/g'
    aaaaa

첫 번째 명령에서 \( ... \| ... \)구문은명확한 행동as (X OR Y), 출력이 통과하기 때문입니다 grep.

두 번째 명령에서 \( ... \| ... \)구문은아무런 조치도 취하지 않은 것 같습니다as (X OR Y), 공백이 밑줄로 변경되지 않기 때문입니다.

(반대로,둘 다\+"한 번 이상 반복됨"으로 인식되는 명령 )

무슨 일이에요? FreeBSD에 두 개의 BRE가 있는 것처럼 보이는 이유는 무엇입니까? 그 중 하나는 구문을 인식하고 다른 하나는 인식하지 못합니까?

더 깊은 문제는 많은 프로젝트가 BRE를 사용하여 다른 UNIX 계열 시스템에 대한 이식성을 제공하기를 희망한다는 것입니다. 그러나 이는 BRE조차도 플랫폼 간에 동일할 가능성이 없다는 것을 보여줍니다.이내에개인 플랫폼. 아?

답변1

링크된 글의 설명이 잘못되었습니다.

실제 POSIX 정의지적했다:

이스케이프 처리되지 않은 <백슬래시>( '\' ) 앞에 오는 일반 문자의 해석은 정의되지 않습니다.[ (){}, 숫자, 괄호 안의 표현]

일반 문자는 .[^$*BRE 특수 문자와 백슬래시 자체를 제외한 모든 문자로 정의됩니다.

따라서 해당 페이지의 선언과 달리 \+BRE는 정의되지 않았으며 \|.

+|일부 정규식 구현에서는 이를 ERE , 특히 GNU와 동일하게 정의합니다 . 그러나 그것에 의존해서는 안 되며 정의된 기능을 고수해야 합니다.

물론 여기서 문제는 ERE 교대 연산자가 |BRE에 존재하지 않으며 ERE에 해당하는 연산자가 +매우 추악하다는 것입니다 \{1,\}. 따라서 대신 ERE를 사용하는 것이 좋습니다.

답변2

$ echo '    aaaaa   ' | sed 's/aaaaa|bbbbb/_/g'
    aaaaa
$ echo '    aaaaa   ' | sed -E 's/aaaaa|bbbbb/_/g'
    _
$ echo '    aaaaa   ' | sed -r 's/aaaaa|bbbbb/_/g'
    _
$ echo '    aaaaa   ' | sed -E '/(aaaaa|bbbbb)/ s/ /_/g'
____aaaaa___
$ echo '    aaaaa   ' | sed -E '/aaaaa|bbbbb/ s/ /_/g'
____aaaaa___

orBRE(기본 정규 표현식)가 아닙니다. -E지정 해야 합니다 .확장하다갈아 바수다.

바라보다GNU 또는 BSD Sed의 정규식 대체/또는 연산자(foo|bar)

고쳐 쓰다

grep이 작동하는 이유는 무엇입니까?

우리가 사용하고 싶은 모드를 선택할 수 있어요grep

  -E, --extended-regexp     PATTERN is an extended regular expression
  -F, --fixed-strings       PATTERN is a set of newline-separated strings
  -G, --basic-regexp        PATTERN is a basic regular expression
  -P, --perl-regexp         PATTERN is a Perl regular expression
  -e, --regexp=PATTERN      use PATTERN as a regular expression

grep이러한 스위치를 사용하면 BRE가 실제로 BRE로 기본 설정되고 OP 표현식이 ERE에서 실패함을 확인할 수 있습니다 .

$ echo '    aaaaa   ' | grep '\(aaaaa\|bbbbb\)'
    aaaaa
$ echo '    aaaaa   ' | egrep '\(aaaaa\|bbbbb\)'
$ echo '    aaaaa   ' | grep -E '\(aaaaa\|bbbbb\)'
$ echo '    aaaaa   ' | grep -G '\(aaaaa\|bbbbb\)'
    aaaaa
$ echo '    aaaaa   ' | grep -G 'aaaaa\|bbbbb'
    aaaaa
$ echo '    aaaaa   ' | grep -G 'aaaaa|bbbbb'
$ echo '    aaaaa   ' | grep -E 'aaaaa|bbbbb'
    aaaaa
$ echo '    aaaaa   ' | grep -E 'aaaaa\|bbbbb'
$ echo '    aaaaa   ' | grep -G 'bbbbb\|aaaaa'
    aaaaa
$ echo '    aaaaa   ' | grep -E 'bbbbb\|aaaaa'
$ echo '    aaaaa   ' | grep -G 'bbbbb|aaaaa'
$ echo '    aaaaa   ' | grep -E 'bbbbb|aaaaa'
    aaaaa

둘 다grep그리고sed인용하다리포맷(7)그것은 분명히 다음과 같이 말합니다:

사용되지 않는("기본") 정규식은 여러 면에서 다릅니다. `|'는 일반 문자이며 기능적으로 동등한 문자가 없습니다.

그러나 "파이프를 탈출"하면 기능을 얻을 수 있는 것 같습니다. 확실히 그런 냄새가 나네요. 게다가 최근 코스가 피해를 입은 것으로 보입니다.regex(3): 최근 BRE 회귀를 다루기 위한 테스트 추가.

대체할 수 있는 직업도 있는 것 같아요정규식libc에서.

Charles Duffy가 아래에 언급했듯이

일부 도구는 백슬래시를 사용하여 BRE 컨텍스트에서 ERE 전용 동작을 얻을 수 있는 비표준 확장을 구현하기 때문입니다.

저는 FreeBSD의 매우 훌륭한 문서에 익숙합니다. 즉, 이것이 의도적이었지만 문서화되지 않은 것인지, 아니면 파손된 것인지 확실하지 않습니다.

관련 정보