ファイルから段落を削除する

ファイルから段落を削除する

file.php次のファイルがあります()。

...
Match user foo
        ChrootDirectory /NAS/foo.info/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no



Match user bar
        ChrootDirectory /NAS/bar.co.uk/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no



Match user baz
        ChrootDirectory /NAS/baz.com/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no

段落の1つを削除するためにbashスクリプトを作成しようとしています。


fooでスクリプトを実行したいとしましょうfile.php

...
Match user bar
        ChrootDirectory /NAS/bar.co.uk/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no



Match user baz
        ChrootDirectory /NAS/baz.com/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no

どうすればいいですか?使い方を考えましたが、sedライナーひとつだけフィットしていると思いますか?

sed -i 's/foo//g' file.php

段落のほとんどの行は一意ではないため、すべての行に対してこれを行うことはできません!どんなアイデアがありますか?

答え1

実際にsed範囲を選択することもできます。このコマンドは、Match user foo最初の空白行(含む)間のすべての行を削除します。

$ sed '/Match user foo/,/^\s*$/{d}' file


Match user bar
        ChrootDirectory /NAS/bar.co.uk/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no



Match user baz
        ChrootDirectory /NAS/baz.com/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no

しかし、個人的には、先行の-00空行を削除する利点があるPerlの短絡モード()を使用してこれを行います。

$ perl -00ne 'print unless /Match user foo/' file
Match user bar
        ChrootDirectory /NAS/bar.co.uk/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no

Match user baz
        ChrootDirectory /NAS/baz.com/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no

どちらの場合も、-iファイルの内部編集を使用できます(これにより、元のファイルのバックアップが作成されますfile.bak)。

sed -i.bak '/Match user foo/,/^\s*$/{d}' file

または

perl -i.bak -00ne 'print unless /Match user foo/' file 

答え2

terdonの答えより少し複雑ですsed

awk '/foo/ {suppress=1} /^\s*$/ {suppress=0} !suppress' file.php

terdonの答えとほぼ同じ結果を生成します。

...



Match user bar
        ChrootDirectory /NAS/bar.co.uk/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no



Match user baz
        ChrootDirectory /NAS/baz.com/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no

つまり、一致する行から始まるすべてのfoo 行を削除(抑制)します。到着スペースのみを含む最初の後続行。入力ファイルの8行、9行、10行file.phpuser fooとの間)user barは空で、出力に表示されます。対照的に、terdonの答えは、一致する行で始まるfoo すべての行を削除します。渡す最初の後続の行には空白のみが含まれているため、8行は削除されますが、9行と10行は残ります。

これはまさにユーザーが要求するものではありません。

awk '/foo/ {suppress=1}
     /^\s*$/ && suppress==1 {suppress=2}
     /[^\s]/ && suppress==2 {suppress=0}
     !suppress' file.php

はい。 (読みやすくするために複数行に分けて1行に入力できます。)これを検出すると、抑制モード#1()fooに入ります。suppress=1サプレッションモード#1に空白行が表示されると、サプレッションモード#2に切り替わる。サプレッションモード#2に空白以外の行が表示されている場合は、モード0に切り替わります。最後に、これは明らかなタスクを実行します。つまり、suppress編集されていない行を印刷します。

関連情報