Nを使用すると、sed出力に対して混同されます。誰かがこの結果を説明できますか?

Nを使用すると、sed出力に対して混同されます。誰かがこの結果を説明できますか?

私はsedを学んでいます。 N(次に複数行)を押すまで、すべてがうまくいくようです。練習/理解/コンテキスト目的でこのファイル(guide.txt)を作成しました。ファイルの内容はこんな感じです。

This guide is meant to walk you through a day as a Network
Administrator. By the end, hopefully you will be better
equipped to perform your duties as a Network Administrator
and maybe even enjoy being a Network Administrator that much more.
Network Administrator
Network Administrator
I'm a Network Administrator

したがって、私の目標は、「ネットワーク管理者」のすべてのインスタンスを「システムユーザー」に置き換えることです。 「Network Admin」の最初のインスタンスは改行(\ n)で区切られているため、「Admin」で始まり「Network \ n」で終わる行を前の行に追加するには、複数行の次の演算子(N)が必要です。大丈夫です。しかし、他のすべての「Network Manager」シングルインスタンスもキャプチャしたいと思います。

私の研究では、改行で区切られた文字列に対して1つ、別の文字列に対して1つという2つの代替コマンドが必要であることを知っています。また、最後の行に代替一致と次の複数行が含まれているため、いくつかのジャイブが発生します。だからこれを作りました...

$ sed '
> s/Network Administrator/System User/
> N
> s/Network\nAdministrator/System\nUser/
> ' guide.txt

これにより、次の結果が返されます。

This guide is meant to walk you through a day as a System
User. By the end, hopefully you will be better
equipped to perform your duties as a System User
and maybe even enjoy being a Network Administrator that much more.
System User
Network Administrator
I'm a System User

私は、1行の置換が「ネットワークマネージャ」のすべての「一般的な」インスタンスをキャプチャして「システムユーザー」に置き換えると思いました。 。予期しない結果。

ちょっと迷って、これを見つけました...

$ sed '
> s/Network Administrator/System User/
> N
> s/Network\nAdministrator/System\nUser/
> s/Network Administrator/System User/
> ' guide.txt

さて、見て、私は欲しい結果を得ました...

This guide is meant to walk you through a day as a System
User. By the end, hopefully you will be better
equipped to perform your duties as a System User
and maybe even enjoy being a System User that much more.
System User
System User
I'm a System User

なぜこれはうまくいきますが、元のsedスクリプトは機能しませんか?私は本当にこれを理解したいと思います。

助けてくれてありがとう。

ベストアンサー1

まず、あなたのソリューションが実際には機能しないことに注意してください。次のテストファイルを検討してください。

$ cat test1
Network
Administrator Network
Administrator

次に、次のコマンドを実行します。

$ sed '
 s/Network Administrator/System User/
 N
 s/Network\nAdministrator/System\nUser/
 s/Network Administrator/System User/
 ' test1
System
User Network
Administrator

問題は、コードが最後のコードを置き換えないことですNetwork\nAdministrator

このソリューションは動作します。

$ sed ':a; /Network$/{$!{N;ba}}; s/Network\nAdministrator/System\nUser/g; s/Network Administrator/System User/g' test1
System
User System
User

私たちはこれを以下にも適用できますguide.txt

$ sed ':a; /Network$/{$!{N;ba}}; s/Network\nAdministrator/System\nUser/g; s/Network Administrator/System User/g' guide.txt 
This guide is meant to walk you through a day as a System
User. By the end, hopefully you will be better
equipped to perform your duties as a System User
and maybe even enjoy being a System User that much more.
System User
System User
I'm a System User

重要なことは、要件に合ったものが見つかるまで1行ずつ読み続けることです。いいえ完了Networkしたら交換できます。

互換性に関する注意:上記はすべて\n代替テキストに使用されます。これにはGNU sedが必要です。 BSD/OSX sed では動作しません。

[方へフィリップス.]

複数行バージョン

理解するのに役立つ場合は、同じコマンドを複数行に分けて説明します。

$ sed ':a
    /Network$/{
       $!{
           N
           ba
       }
    }
    s/Network\nAdministrator/System\nUser/g
    s/Network Administrator/System User/g
    ' filename

どのように動作しますか?

  1. :a

    これでラベルが作成されますa

  2. /Network$/{ $!{N;ba} }

    行がで終わると、Network次のようになります。いいえ最後の行($!)は次の行(N)を読み取り、追加し、ラベルaba)に再分岐します。

  3. s/Network\nAdministrator/System\nUser/g

    中間改行文字に置き換えてください。

  4. s/Network Administrator/System User/g

    中間スペースに置き換えます。

より簡単なソリューション(GNUのみ)

GNU sedを使用する(いいえBSD/OSX)、代替コマンドのみが必要です。

$ sed -zE 's/Network([[:space:]]+)Administrator/System\1User/g' test1
System
User System
User

そしてguide.txtファイルへ:

$ sed -zE 's/Network([[:space:]]+)Administrator/System\1User/g' guide.txt 
This guide is meant to walk you through a day as a System
User. By the end, hopefully you will be better
equipped to perform your duties as a System User
and maybe even enjoy being a System User that much more.
System User
System User
I'm a System User

この例では、-zsed に最初の NUL 文字を読み取るように指示します。テキストファイルにはヌル文字を含めることができないため、ファイル全体を一度に読み取る効果があります。これにより、行を失うことを心配することなく置換を実行できます。

ファイルが大きい場合(通常はギガバイトを意味する)、この方法は適切ではありません。大きすぎる場合は、一度に読み取るとシステムRAMに負担がかかる場合があります。

GNUおよびBSD sed用のソリューション

提案通りフィリフォス、ポータブルソリューションは次のとおりです。

sed 'H;1h;$!d;x;s/Network\([[:space:]]\)Administrator/System\1Us‌​er/g'

おすすめ記事