我的印像是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
s 會從文字行中去除空白字符,而避免這種情況的唯一方法是轉義前導空白,正如這些上世紀的手冊頁所解釋的那樣:1,2,3
這同樣適用BSD
sed
(OSX
只是複製了代碼,這不是他們的擴展名),如果您檢查檔案並閱讀man
頁面來自BSD 2.11
很清楚:
(1)我\
文字
.......
表示的一個參數文字'\'
由一行或多行組成,除了最後一行之外,所有行都以隱藏換行符號結尾。文字中的反斜杠被視為's'
命令替換字串中的反斜杠,並且可用於保護初始空白和製表符免受在每個腳本行上進行的剝離。
現在,這在 POSIX 規範中記錄在哪裡?它只說
參數文字應由一行或多行組成。文本中每個嵌入的<newline> 前面應有一個<backslash>。文字中的其他<反斜線>字元應被刪除,並且後面的字元應按字面意思處理。
如果你向下捲動到基本原理它說
在命令列中接受 <blank> 和 <space> 字元的要求比早期的提案更加明確,以清楚地描述歷史實踐並消除對短語「保護初始空白[原文如此]和製表符不被剝離」的混淆這是在每個腳本行上完成的”,出現在sed 實用程式文字描述的大部分歷史文件中。 (並非所有實作都已從文字行中刪除 <blank> 字符,儘管它們都允許在命令列上的地址前面添加前導 <blank> 字符。)
由於部分與“反斜線可以用來”未包含在該引用中,其餘短語“保護初始空白...”沒有任何意義... 1
不管怎樣,總而言之:一些實作確實(有些仍然這樣做)從文字行中去除空白。然而,由於所有實作都應遵守的 POSIX 規範規定
文字中的其他<反斜線>字元應被刪除,並且後面的字元應按字面意思處理。
我們可以得出結論,在要插入的文本中縮進行的可移植方法是轉義每行的前導空格。
1:我也不明白為什麼OSX
/BSD
人們在不更改原始程式碼的情況下更改了man
頁面中的整個段落 - 您會得到與以前相同的行為,但記錄這些內容的 man 部分不再存在。
答案2
它是 OSXsed
擴展,而不是標準行為。你可以看到此連結在功能上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
宏來吃掉空間。
在 FreeBSD 中sed
,當使用, ,時可能會錯誤地將其\
視為行繼續字符,這種行為更加奇怪。在我的 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
康格姆給了最佳答案,但為了記錄,這裡是GNU sed
做:
echo foo | sed 'i\
This line starts with spaces.'
輸出:
This line starts with spaces.
foo