私は、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、3BSD
sed
(OSX
コードをコピーしただけで、拡張機能ではありません)アーカイブをチェックして読んでみれば 、man
ページからBSD 2.11
それはかなり明白です:
(1)i\
文章
.......
引数は文章1 行以上の行で構成され、最後の行を除くすべての行は'\'
改行を隠すために で終わります。テキスト内のバックスラッシュは、コマンドの置換文字列内のバックスラッシュと同様に扱われ's'
、スクリプトの各行で行われる削除から最初の空白とタブを保護するために使用できます。
さて、POSIX仕様のどこにこれが記載されているのでしょうか?そこにはこう書いてあるだけです
引数テキストは 1 行以上で構成されます。テキストに埋め込まれた各 <newline> の前には <backslash> が付きます。テキスト内のその他の <backslash> 文字は削除され、次の文字は文字どおりに扱われます。
そして下にスクロールすると根拠それは言う
コマンドラインで <blank> および <space> 文字を受け入れるための要件は、以前の提案よりも明確にされました。これは、歴史的慣行を明確に記述し、sed ユーティリティのテキスト記述の歴史的ドキュメントの多くに見られる「スクリプトの各行で行われる削除から最初の空白とタブを保護する」というフレーズに関する混乱を排除するためです。(すべての実装でテキスト行から <blank> 文字が削除されたわけではありませんが、コマンドラインのアドレスの前に先頭の <blank> 文字があることは許可されています。)
の部分から「バックスラッシュは、次の場合に使用できます」その引用文には含まれていなかったが、残りのフレーズ「最初の空白を保護する...」意味が分からない... 1
とにかく、まとめると、いくつかの実装ではテキスト行から空白を削除していました(そしていくつかは今でも削除しています)。しかし、すべての実装が準拠すべきPOSIX仕様では、
テキスト内の他の <backslash> 文字は削除され、次の文字は文字通りに扱われます。
挿入するテキストの行をインデントする移植可能な方法は、各行の先頭の空白をエスケープすることであると結論付けることができます。
1: また、ソース コードを変更せずにページ内の段落全体を変更した理由OSX
もわかりません。以前と同じ動作が得られますが、この内容を文書化した man セクションはもう存在しません。BSD
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
。
FreeBSD ではsed
、 、\
を使用すると行継続文字として誤って処理される可能性がありa
、動作はさらに奇妙になります。私の FreeBSD 9.3 では次のようになります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