나는 그에게서 감동을 받았다.POSIX 사양sed
i\
출력에 공백을 넣지 않으려면 명령 다음 줄의 텍스트를 왼쪽 정렬해야 합니다 .
내 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 사양에 따르면
텍스트의 다른 <백슬래시> 문자는 제거되고, 다음 문자는 문자 그대로 처리됩니다.
삽입할 텍스트의 줄을 들여쓰기하는 이식 가능한 방법은 각 줄의 선행 공백을 이스케이프 처리하는 것이라고 결론 내릴 수 있습니다.
OSX
1: 나는 또한 왜 / 사람들 이 소스 코드를 변경하지 않고 페이지 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에서는:\
a
i
c
$ 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