:a; $!N;の意味は何ですか sedコマンドで?


11
$ (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)の部分の機能を知りません。



最後の部分はどうですか?
Avinash Raj

「t」コマンドは、最後の置換コマンドがパターンスペースを変更した場合、名前付きラベルに分岐します。
シャオドンジ

回答:


17

これらは、明らかに不可解な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'

1
!$は最後の改行、IMOと一致しません。
Braiam 2014

@Braiamはそれについてあまり確信がありません、それ$!はそうではありません!$。しかし、それはまたかもしれません。!N$!
terdon 2014

texinfoページを解析しようとしましたが、!Nまたはへの参照が見つかりませんでした$!。そのため、最後の行が改行であるかEOFであるかを検討しているという考えを続けています。
Braiam 2014

4
$!は後置補数演算子を持つアドレス「範囲」と考えようとしています- $!NNアドレス以外はどこでも行う$)はm,n!d(行mを除くすべてを削除するn)のようなものと実際に同じ構文です。
スチールドライバー、2014

:gotoラベルの類似物であり、実際にはThompsonシェルでgotoラベルとして:使用されていたため、sedシェルとThompsonシェルの両方を使用する当時の人々には馴染みのあるものです
Sergiy Kolodyazhnyy

0

私が多くの混乱を参照してくださいので、私はこの回答を投稿する理由を実行するときに最後の行が除外されているN(文字列を扱うライン経由$!)とOPはの意味について混乱していたため:a;$!N; にsedコマンド、のみならず、彼は掲載特定の1 。

コマンドの最後の行で "重要な"(読み取りを続ける)コマンドが実行されないため、(OPおよび@terdonによって)提案された例では、$!N代わりにを使用する利点はN明白ではありませんN。(実際、その行アドレスを削除しても結果は同じです。)

より複雑な例(たとえば、this sentence2つの単語が1行に表示されたり、2行に表示されたりするファイルで置換する)では、Nコマンドの最後の行を除外することが重要になる可能性があります。最後の行が除外されていない場合、その行で実行Nすると、がsedヒットしてEOFすぐに終了し、後続のすべてのコマンド(分岐コマンド、つまりtおよびb)が実行されなくなります。

非常に単純化した例では、一致するものがないため、中止されたコマンドが実行されても何も実行されないため、削除して実行を失敗$!させて戻ることができます。sedNs\n

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.