sed의 'i\' 명령에 대한 인수를 들여쓰기하는 것이 이식 가능합니까?

sed의 'i\' 명령에 대한 인수를 들여쓰기하는 것이 이식 가능합니까?

나는 그에게서 감동을 받았다.POSIX 사양sedi\출력에 공백을 넣지 않으려면 명령 다음 줄의 텍스트를 왼쪽 정렬해야 합니다 .

내 Mac에서 BSD sed를 사용하여 빠르게 테스트해 본 결과 아마도 이것이~ 아니다필요한:

$ cat test.sed 
#!/bin/sed -f
i\
      This line starts with spaces.
$ echo some text | sed -f test.sed
This line starts with spaces.
some text
$ 

그러나 이 문서를 어디에서도 찾을 수 없는 것 같습니다. POSIX 사양에도 없고 sed내 시스템의 의 매뉴얼 페이지 에도 없습니다 .

sed이식성을 원하는 스크립트 에서 이 동작을 신뢰할 수 있습니까 ? 휴대성은 얼마나 되나요?

(문서화되어 있나요?어딘가에?)


sed(보너스 질문: 에 전달된 고정 줄의 시작 부분에 공백을 강제로 삽입하는 것이 가능합니까 i\?)

답변1

아니요. 하지만 선행 공백을 벗어나기만 하면 스크립트를 이식할 수 있습니다. 왜 ? 일부 sed는 텍스트 줄에서 공백 문자를 제거하고 이를 방지하는 유일한 방법은 지난 세기의 다음 매뉴얼 페이지에서 설명하는 것처럼 선행 공백을 탈출하는 것입니다.1,2,
BSD sed( OSX그냥 코드를 복사한 것 뿐이고 확장자가 아님) 에도 마찬가지입니다. 아카이브를 확인하고man페이지의BSD 2.11꽤 분명합니다.

(1)나\
텍스트
.......
인수는 다음과 같이 표시됩니다.텍스트하나 이상의 줄로 구성되며, 마지막 줄을 제외한 모든 줄은 '\'개행을 숨기기 위해 로 끝납니다. 텍스트의 백슬래시는 명령의 대체 문자열에서 백슬래시처럼 처리되며 's' 모든 스크립트 줄에서 수행되는 제거로부터 초기 공백과 탭을 보호하는 데 사용될 수 있습니다.

이제 POSIX 사양의 어디에 문서화되어 있습니까? 그것은 단지 말한다

인수 텍스트는 하나 이상의 줄로 구성됩니다. 텍스트에 포함된 각 <newline> 앞에는 <backslash>가 와야 합니다. 텍스트의 다른 <백슬래시> 문자는 제거되고, 다음 문자는 문자 그대로 처리됩니다.

그리고 아래로 스크롤하면이론적 해석그것은 말한다

명령줄에서 <blank> 및 <space> 문자를 허용하기 위한 요구 사항은 역사적 관행을 명확하게 설명하고 "초기 공백 [원문] 및 탭을 제거에서 보호"라는 문구에 대한 혼란을 제거하기 위해 초기 제안보다 더 명확해졌습니다. sed 유틸리티 텍스트 설명에 대한 많은 역사적 문서에 나타나는 "모든 스크립트 줄에서 수행됩니다." (모든 구현이 텍스트 줄에서 <공백> 문자를 제거한 것으로 알려진 것은 아니지만, 모두 명령줄에서 주소 앞에 <공백> 문자를 허용했습니다.)

가 있는 부분부터"백슬래시는 다음 용도로 사용될 수 있습니다."해당 인용문에는 포함되지 않았으며 나머지 문구는"초기 공백을 보호하세요..."말도 안 돼... 1


어쨌든 요약하면 일부 구현에서는 텍스트 줄에서 공백을 제거했습니다(그리고 일부는 여전히 수행합니다). 그러나 모든 구현이 준수해야 하는 POSIX 사양에 따르면

텍스트의 다른 <백슬래시> 문자는 제거되고, 다음 문자는 문자 그대로 처리됩니다.

삽입할 텍스트의 줄을 들여쓰기하는 이식 가능한 방법은 각 줄의 선행 공백을 이스케이프 처리하는 것이라고 결론 내릴 수 있습니다.


OSX1: 나는 또한 왜 / 사람들 이 소스 코드를 변경하지 않고 페이지 BSD의 전체 단락을 변경했는지 이해할 수 없습니다 . 이전과 동일한 동작을 얻지만 이 항목을 문서화하는 man 섹션은 더 이상 존재하지 않습니다.man

답변2

표준 동작이 아닌 OSX 확장입니다 sed. 너는 볼 수있어이 링크는 기능상compile_text:

/*
 * Compile the text following an a or i command.
 */
static char *
compile_text()
{
    int asize, size;
    char *text, *p, *op, *s;
    char lbuf[_POSIX2_LINE_MAX + 1];

    asize = 2 * _POSIX2_LINE_MAX + 1;
    text = xmalloc(asize);
    size = 0;
    while (cu_fgets(lbuf, sizeof(lbuf))) {
        op = s = text + size;
        p = lbuf;
        EATSPACE();
        for (; *p; p++) {
            if (*p == '\\')
                p++;
            *s++ = *p;
        }
        size 

그들은 EATSPACE매크로를 사용하여 공간을 먹었습니다.

, , 를 사용할 때 줄 연속 문자로 sed잘못 처리될 수 있는 FreeBSD에서는 동작이 더 이상합니다. 내 FreeBSD 9.3에서는:\aic

$ echo 1 | sed -e 'i\ 1'
": extra characters after \ at the end of i command

하지만:

$ echo 1 | sed -e 'i\
 2'
2
1

작동하고 공간도 잡아먹습니다.

GNU sed, 가보에는 sed이 문제가 없습니다.

답변3

Cuonglm가장 좋은 답변을 주었습니다, 하지만 참고로 여기에 있는 내용은 다음과 같습니다.암소 비슷한 일종의 영양 sed하다:

echo foo | sed 'i\
     This line starts with spaces.'

산출:

     This line starts with spaces.
foo

관련 정보