수색…


소개

@ SnoringFrog의 주제 생성 요청에서 인용하려면 :

"sed를 사용하는 가장 큰 장애물 중 하나는 스크립트가 하나가 아닌 다른 스크립트가 아니기 때문에 실패 (또는 예기치 않은 방식으로 성공)하는 스크립트입니다. 더 큰 차이점을 단순하게 제거하면 좋을 것입니다."

비고

macOSBSD 버전의 sed [1] 를 사용하는데, 이것은 리눅스 배포판에 포함 된 GNU sed 버전과 많은면에서 다릅니다.

그들의 공통 분모POSIX에 의해 선언 된 기능입니다 : POSIX sed spec을보십시오.

가장 이식 가능한 접근 방식기능을 제한 하는 POSIX 기능 만 사용 하는 것입니다 .

  • 특히, POSIX는 제한이 많은 기본 정규 표현식 (예 : | (변경)에 대한 지원이 전혀없고, +? 대한 직접적인 지원이 없음) 및 다른 이스케이프 요구 사항에 대해서만 지원을 지정합니다.

    • 주의 사항 : GNU sed ( -r 없이) \| 지원합니다. , \+\? POSIX와 호환되지 않습니다. 비활성화하려면 --posix 를 사용 하십시오 (아래 참조).
  • POSIX 기능 만 사용하려면

    • (두 버전 모두) : -n-e 옵션 사용하십시오 (특히 확장 정규 표현식에 대한 지원을 사용하려면 -E 또는 -r 을 사용하지 마십시오)

    • GNU sed : POSIX 전용 기능을 보장하기 위해 --posix 옵션을 추가하십시오 (꼭 필요하지는 않지만, 주의 하지 않고 비 POSIX 기능을 우연히 --posix 있습니다 .) : --posix 자체 는 POSIX 호환이 아닙니다. )

    • POSIX 전용 기능을 사용하면 더 엄격한 포맷팅 요구 사항을 의미합니다 (GNU sed 에서 많은 편의를 sed ).

      • 일반적으로 \n\t 와 같은 제어 문자 시퀀스는 지원되지 않습니다.
      • 레이블과 분기 명령 (예 : b ) 뒤에는 별도의 -e 옵션을 통해 실제 개행이나 연속이 있어야합니다 .
      • 자세한 내용은 아래를 참조하십시오.

그러나 버전 모두 POSIX 표준 확장 을 구현 합니다 .

  • 그것들이 구현 하는 확장 기능은 다르다 (GNU sed 는 더 많은 것을 구현한다).
  • 이들이 모두 구현 한 확장부분적으로 구문이 다릅니다 .

두 플랫폼을 모두 지원해야하는 경우 (차이점 설명) :

  • 호환되지 않는 기능 :

    • 인수 없이 -i 옵션 을 사용 하면 (백업없이 현재 위치에서 업데이트 중) 호환되지 않습니다.

      • BSD sed : 반드시 -i '' 사용해야한다.
      • GNU sed : 반드시 -i (동등한 : -i'' )를 사용해야합니다 - -i '' 사용하면 작동하지 않습니다.
    • -i GNU sed최근 버전의 BSD sed (예 : FreeBSD 10)에서 입력 파일 당 줄 번호현명하게 켭니다. 그러나 macOS에서는 10.12부터 사용 하지 않습니다 .
      -i 가 없으면 모든 버전이 입력 파일에 누적 적으로 숫자 줄을 표시합니다.

    • 마지막 입력 행에 후행 줄 바꿈이 없고 인쇄됩니다.

      • BSD sed : 입력 행이 하나로 끝나지 않더라도 항상 출력에 개행 문자추가합니다 .
      • GNU sed : 후행 줄 바꿈 상태를 유지합니다 . 즉, 입력 줄이 하나만있는 경우에만 줄 바꿈을 추가합니다.
  • 공통 기능 :

    • sed 스크립트를 BSD sed 지원하는 것으로 제한하면, 일반적으로 -E 와 함께 플랫폼 특정 확장 정규 표현식 기능을 사용하는 것을 제외하고는 GNU sed 에서도 작동합니다. 분명히, GNU 버전에만 해당하는 확장 기능도 사용할 수 없습니다. 다음 섹션을 참조하십시오.

BSD 버전의 엄격한 요구 사항에 따라 크로스 플랫폼 지원 (OS X / BSD, Linux)에 대한 지침 :

MacOSLinux 는 BSD와 GNU 버전의 sed 를 가리키는 데 종종 사용되는데, 이는 각 플랫폼의 주식 버전이기 때문입니다. 그러나 brew install gnu-sed 와 함께 Homebrew 를 사용하여 macOS에 GNU sed 를 설치할 수 있습니다.

: -r-E 플래그 ( 확장 정규 표현식)를 사용하는 경우를 제외하고는 아래 지침은 POSIX 호환 sed 스크립트 작성에 해당합니다.

  • POSIX를 준수하려면 유감스럽게도 이름에서 알 수 있듯이 매우 기본적인 POSIX BRE ( 기본 정규식)로 제한해야합니다.
    주의 사항 : \| , \+\? 지원됩니다 : --posix 가 사용되지 않는 한 GNU sed 가 지원하지만, BSD sed 는 지원하지 않습니다. 이러한 기능은 POSIX와 호환 되지 않습니다 .
    \+\? POSIX 호환 방식 으로 에뮬레이트 될 있습니다 .
    \{1,\}\+ ,
    \{0,1\} 대한 \? ,
    \| (교대) , 불행히도, 수 없습니다 .

  • 좀 더 강력한 정규 표현식을 사용하려면 ERE ( 확장 정규 표현식 )를 지원하기 위해 -E ( -r 대신 )를 사용하십시오 (GNU sed-E 문서화하지 않지만 -r 의 별명으로 작동합니다), 새로운 버전의 BSD sed , FreeBSD 10에서와 같이 이제는 -r 을 지원하지만, 10.12에서의 macOS 버전은 그렇지 않습니다 .
    주의 사항 : -r / -E 사용하더라도 명령이 POSIX와 호환 되지 않는다고 하더라도 POSIX ERE (확장 정규 표현식)로 제한 해야합니다. 슬프게도, 이것은 당신이 여러 유용한 구조를 사용할 수 없다는 것을 의미합니다 :

    • 워드 경계 어설 션은 플랫폼에 따라 다르므로 (예 : Linux에서는 \< , OS X에서는 [[:<]] ).
    • (캡처-그룹의 대체 문자열에서 일치하는 "백 참조"반대로 정규 표현식 내부의 백 참조 s BSD의 때문에, 함수 호출) sed 그렇게하지, 호기심, 확장 된 정규 표현식에 그들을 지원하지 않습니다 (하지만 기본적인 것들, 그들은 POSIX 위임 된 곳이다).
  • \n\t 와 같은 제어 문자 이스케이프 시퀀스 :

    • regexes (라인 선택을위한 패턴과 s 함수의 첫 번째 인자 모두)에서, \n 만 이스케이프 시퀀스로 인식된다고 가정합니다 (거의 사용되지 않습니다. 패턴 공간은 일반적으로 \n 을 종결하지 않고 단일 행이기 때문에). 예를 들어이, 있도록하지만, 문자 클래스 내부가 아니라 [^\n] .; 작동하지 않습니다 귀하의 의견이 더 제어 문자가없는 경우 이외 ( \t , 당신은 에뮬레이션 할 수 있습니다 [^\n][[:print:][:blank:]] . 그렇지 않으면, 스플 라이스 제어 문자가 리터럴로 [2]) - 일반적으로 통해 중, 리터럴과 같은 제어 문자를 포함 접합 된 ANSI C-인용 문자열 (예를 들어, $'\t' )에서 ( bash, ksh, zsh )를 지원하거나 printf (예 : "$(printf '\t')" )를 사용하여 명령 대체를 통해 수행 할 수 있습니다.

      • Linux 전용 :
        sed 's/\t/-/' <<<$'a\tb' # -> 'a-b'
      • OSX Linux :
        sed 's/'$'\t''/-/' <<<$'a\tb' # ANSI C-quoted string
        sed 's/'"$(printf '\t')"'/-/' <<<$'a\tb' # command subst. with printf
    • s 명령과 함께 사용되는 대체 문자열에서 제어 문자 이스케이프 시퀀스가 ​​지원되지 않는다고 가정합니다. 다시 제어 문자를 포함합니다. 위와 같이 리터럴 로.

      • Linux 전용 :
        sed 's/-/\t/' <<<$'ab' # -> 'a<tab>b'
      • macOS Linux :
        sed 's/-/'$'\t''/' <<<'a-b'
        sed 's/-/'"$(printf '\t')"'/' <<<'a-b'
    • 받는 텍스트 인수에 대한 동감 i 과 기능 : 제어 문자 시퀀스를 사용하지 않는 - 아래를 참조하십시오. a

  • 라벨과 브랜칭 : bt 함수에 대한 label-name 인수 뿐만 아니라 라벨 에는 리터럴 개행 문자 또는 스플 라이스 된 $'\n' 이 와야합니다 . 또는 여러 개의 -e 옵션을 사용하고 레이블 이름 뒤에 각 오른쪽 끝을 지정하십시오.

    • Linux 전용 :
      sed -n '/a/ bLBL; d; :LBL p' <<<$'a\nb' # -> 'a'
    • macOS Linux :
      • 둘 중 하나 (실제 줄 바꿈) :
        sed -n '/a/ bLBL d; :LBL p' <<<$'a\nb'
      • OR (spliced-in $\n 인스턴스) :
        sed -n '/a/ bLBL'$'\n''d; :LBL'$'\n''p' <<<$'a\nb'
      • OR (여러 개의 -e 옵션) :
        sed -n -e '/a/ bLBL' -e 'd; :LBL' -e 'p' <<<$'a\nb'
  • 텍스트 삽입 / 추가를위한 함수 ia : 텍스트 인수를 지정하기 전에 함수 이름 뒤에 \ 붙이고, 리터럴 개행 문자 나 스플라인 인 $'\n' 따라야합니다 .

    • Linux 전용 :
      sed '1 i new first line' <<<$'a\nb' # -> 'new first line<nl>a<nl>b'
    • OSX Linux :
      sed -e '1 i\'$'\n''new first line' <<<$'a\nb'
    • 노트 :
      • -e 없으면 텍스트 인수는 macOS (bug?)의 출력에서 ​​줄 바르게 종료되지 않습니다.
      • 텍스트 인수에서 \n\t 같은 제어 문자 이스케이프 는 Linux에서만 지원되므로 사용하지 마십시오 .
      • 따라서 텍스트 인수에 실제 내부 줄 바꿈 문자가 있으면 \ 이스케이프합니다.
      • 텍스트 인수 다음에 추가 명령을 배치하려면 리터럴 또는 스플라인이 적용된 (이스케이프되지 않은) 개행 문자로 종료하거나 별도의 -e 옵션을 사용하여 종료해야합니다 (모든 버전에 적용되는 일반적인 요구 사항) .
  • 기능 목록 내부 (여러 기능에 동봉 호출 {...} , 또한 닫기 전에 마지막 기능을 종료해야합니다) }; .

    • Linux 전용 :
      • sed -n '1 {p;q}' <<<$'a\nb' # -> 'a'
    • macOS Linux :
      • sed -n '1 {p;q;}' <<<$'a\nb'

GNU sed 특정 기능 이 BSD sed 에서 빠져있다.

두 플랫폼을 모두 지원해야하는 경우에 놓칠 GNU 기능 :


[1] macOS sed 버전은 FreeBSD 및 PC-BSD와 같은 다른 BSD 계열 시스템의 버전보다 오래된 버전입니다. 불행히도 이것은 예를 들어 FreeBSD에서 작동하는 기능이 macOS에서 작동한다고 가정 할 수 없다는 것을 의미합니다.

[2] ANSI C 인용 문자열 $'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'\n (및 NUL)을 제외한 모든 ASCII 제어 문자를 포함하므로 [:print:] 와 조합하여 사용할 수 있습니다 [:print:] [^\n] 의 매우 견고한 에뮬레이션을 위해 :
'[[:print:]'$'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'']

모든 개행을 탭으로 대체하십시오.

참고 : 간결함을 위해 명령은 here-strings ( <<< )ANSI C- 인용 문자열 ( $'...' )을 사용 합니다. 이 두 쉘 기능은 bash , kshzsh 에서 작동합니다.

# GNU Sed
$ sed ':a;$!{N;ba}; s/\n/\t/g' <<<$'line_1\nline_2\nline_3'
line_1 line_2 line_3

# BSD Sed equivalent (multi-line form)
sed <<<$'line_1\nline_2\nline_3' '
:a
$!{N;ba
}; s/\n/'$'\t''/g'

# BSD Sed equivalent (single-line form, via separate -e options)
sed -e ':a' -e '$!{N;ba' -e '}; s/\n/'$'\t''/g' <<<$'line 1\nline 2\nline 3'

BSD Sed 노트 :

  • 실제 개행이나 별도의 -e 옵션을 사용 :a 레이블 ( :a ) 및 분기 명령 ( ba )을 종료해야 할 필요성에 유의하십시오.

  • \t 와 같은 제어 문자 이스케이프 시퀀스는 대체 문자열에서 지원되지 않으므로 ANSI C 인용 탭 리터럴 이 대체 문자열로 연결됩니다.
    ( 정규 표현식 부분에서 BSD Sed는 \n 을 이스케이프 시퀀스 로만 인식합니다.)

리터럴 텍스트를 함수 'a'가있는 행에 추가합니다.

참고 : 간결함을 위해 명령은 here-strings ( <<< )ANSI C- 인용 문자열 ( $'...' )을 사용 합니다. 이 두 쉘 기능은 bash , kshzsh 에서 작동합니다.

 # GNU Sed
 $ sed '1 a appended text' <<<'line 1'
 line 1
 appended text

 # BSD Sed (multi-line form)
 sed '1 a\
 appended text' <<<'line 1'

 # BSD Sed (single-line form via a Bash/Ksh/Zsh ANSI C-quoted string)
 sed $'1 a\\\nappended text' <<<'line 1'

BSD Seed가 추가 할 텍스트를 전달하기 위해 실제 줄 바꿈 뒤에 \ 가 필요한 방법에 유의하십시오.
관련 i (삽입) 및 c (삭제 및 삽입) 기능에도 동일하게 적용됩니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow