$ (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
)の部分の機能を知りません。
$ (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
):
:label
bおよびtコマンドのラベル。tラベル
最後の入力行が読み取られてから、および最後のtまたはTコマンド以降にas ///が正常に置換された場合、labelに分岐します。ラベルが省略されている場合、スクリプトの最後に分岐します。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'
$!
はそうではありません!$
。しかし、それはまたかもしれません。!N
$!
!N
またはへの参照が見つかりませんでした$!
。そのため、最後の行が改行であるかEOFであるかを検討しているという考えを続けています。
$!
は後置補数演算子を持つアドレス「範囲」と考えようとしています- $!N
(N
アドレス以外はどこでも行う$
)はm,n!d
(行m
を除くすべてを削除するn
)のようなものと実際に同じ構文です。
私が多くの混乱を参照してくださいので、私はこの回答を投稿する理由を実行するときに最後の行が除外されているN
(文字列を扱うライン経由$!
)とOPはの意味について混乱していたため:a;$!N;
にsedコマンド、のみならず、彼は掲載特定の1 。
コマンドの最後の行で "重要な"(読み取りを続ける)コマンドが実行されないため、(OPおよび@terdonによって)提案された例では、$!N
代わりにを使用する利点はN
明白ではありませんN
。(実際、その行アドレスを削除しても結果は同じです。)
より複雑な例(たとえば、this sentence
2つの単語が1行に表示されたり、2行に表示されたりするファイルで置換する)では、N
コマンドの最後の行を除外することが重要になる可能性があります。最後の行が除外されていない場合、その行で実行N
すると、がsed
ヒットしてEOF
すぐに終了し、後続のすべてのコマンド(分岐コマンド、つまりt
およびb
)が実行されなくなります。
非常に単純化した例では、一致するものがないため、中止されたコマンドが実行されても何も実行されないため、削除して実行を失敗$!
させて戻ることができます。sed
N
s
\n