How to Remove a Paragraph from a File

bashsedshelltext processing

I have a file (file.php) like this:

...
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

I am trying to write a bash script to delete one of the paragraphs.


So say I wanted delete the user foo from the file.php. After running the script, it would then look like this:

...
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

How could I go about doing this. I have thought about using sed but that only seems to be appropriate for one liners?

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

And I couldn't do it for each individual line as most of the lines withing the paragraph are not unique! Any ideas?

Best Answer

Actually, sed can also take ranges. This command will delete all lines between Match user foo and the first empty line (inclusive):

$ 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

Personally, however, I would do this using perl's paragraph mode (-00) that has the benefit of removing the leading blank lines:

$ 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

In both cases, you can use -i to edit the file in place (these will create a backup of the original called file.bak):

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

or

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