从文件中删除段落

从文件中删除段落

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

我正在尝试编写一个 bash 脚本来删除其中一个段落。


假设我想foofile.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

然而,就我个人而言,我会使用 Perl 的段落模式 ( -00) 来执行此操作,该模式的优点是删除前导空白行:

$ 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.php(在user 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

是。 (为了便于阅读,将其分成多行;可以将其全部输入一行。)当它看到 时foo,它会进入抑制模式#1 ( suppress=1)。当它在抑制模式 #1 下看到空行时,它会切换到抑制模式 #2。当它在抑制模式 #2 下看到非空行时,它会切换到模式 0。最后,它会执行显而易见的操作 — 打印未suppress编辑的行。

相关内容