$ (echo hello; echo there) | sed ':a;$!N;s/\n/string/;ta'
hellostringthere
上記のsed
コマンドは、改行文字をストリング「string」に置き換えます。しかし、単一引用符内の:a;$!N;s/\n/string/;ta
の意味がわかりません。中間部分s/\n/string/
を知っています。しかし、最初(:a;$!N;
)と最後(ta
)の部分の機能はわかりません。
これらは、明らかに不可解なsed
コマンドです。具体的には(man sed
から):
:ラベル
bおよびtコマンドのラベル。tラベル
。ラベルが省略されている場合は、スクリプトの最後に分岐します。n N入力の次の行をパターンスペースに読み込み/追加します。
したがって、投稿したスクリプトは、次のように分類できます(読みやすいようにスペースを追加します)。
sed ':a; $!N; s/\n/string/; ta'
--- ---- ------------- --
| | | |--> go back (`t`) to `a`
| | |-------------> substitute newlines with `string`
| |----------------------> If this is not the last line (`$!`), append the
| next line to the pattern space.
|----------------------------> Create the label `a`.
基本的に、これがしていることは、擬似コードで次のように書くことができます。
while (not end of line){
append current line to this one and replace \n with 'string'
}
より複雑な入力例を使用すると、これをもう少しよく理解できます。
$ printf "line1\nline2\nline3\nline4\nline5\n" | sed ':a;$!N;s/\n/string/;ta'
line1stringline2stringline3stringline4stringline5
!$
が必要な理由はよくわかりません。私が知る限り、同じ出力を得ることができます
printf "line1\nline2\nline3\nline4\nline5\n" | sed ':a;N;s/\n/string/;ta'
whyについて多くの混乱が見られるので、N
を実行するときに最後の行が除外されます(行アドレス文字列$!
を通じて)、OPの意味について混乱しているため、この回答を投稿します:a;$!N;
in a sed command、彼が投稿した特定のtheだけでなく。
さて、N
の代わりに$!N
を使用する利点は、N
の後の最後の行で "重要"(読み続ける)コマンドが実行されないため、提案された例(OPおよび@terdon)では明白ではありませんコマンド。 (実際、その行アドレスを削除しても結果は同じです。)
より複雑な例(たとえば、ファイル内のthis sentence
を置換し、2つの単語を1行と2行に表示することもあります)、N
コマンドの最後の行を除外することが重要です!最後の行が除外されていない場合、その上でN
を実行すると、sed
はEOF
にヒットしてすぐに終了し、後続のすべてのコマンド(分岐コマンド、つまりt
およびb
)が実行されなくなります。
単純すぎる例では、$!
を安全に削除し、sed
をN
の実行に失敗させ、一致する\n
がないため、中止されたs
コマンドが実行されても何もしません。