从文件中删除段落

max*_*sme 7 shell bash sed text-processing

我有一个这样的文件(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
Run Code Online (Sandbox Code Playgroud)

我正在尝试编写一个 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
Run Code Online (Sandbox Code Playgroud)

我怎么可能去做这件事。我想过使用,sed但这似乎只适用于一个衬垫?

sed -i 's/foo//g' file.php
Run Code Online (Sandbox Code Playgroud)

而且我无法为每一行都这样做,因为该段落中的大多数行都不是唯一的!有任何想法吗?

ter*_*don 7

实际上,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
Run Code Online (Sandbox Code Playgroud)

但是,就我个人而言,我会使用 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
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,您都可以使用-i就地编辑文件(这些将创建名为 的原始文件的备份file.bak):

sed -i.bak '/Match user foo/,/^\s*$/{d}' file
Run Code Online (Sandbox Code Playgroud)

或者

perl -i.bak -00ne 'print unless /Match user foo/' file 
Run Code Online (Sandbox Code Playgroud)


Sco*_*ott 5

sed比 terdon\xe2\x80\x99s答案稍微复杂一点:\n

\n\n
awk \'/foo/ {suppress=1} /^\\s*$/ {suppress=0} !suppress\' file.php\n
Run Code Online (Sandbox Code Playgroud)\n\n

产生与 terdon\xe2\x80\x99s 答案几乎完全相同的结果:

\n\n
...\n\n\n\nMatch user bar\n        ChrootDirectory /NAS/bar.co.uk/\n        ForceCommand internal-sftp\n        AllowTcpForwarding no\n        GatewayPorts no\n        X11Forwarding no\n\n\n\nMatch user baz\n        ChrootDirectory /NAS/baz.com/\n        ForceCommand internal-sftp\n        AllowTcpForwarding no\n        GatewayPorts no\n        X11Forwarding no\n
Run Code Online (Sandbox Code Playgroud)\n\n

即,它删除(抑制)每一行\n从匹配的行开始,foo\n直到第一个仅包含空格的后续行。\xc2\xa0\n第 8、9 和 10 行,在file.php输入文件中为空白\n (在user foo和之间user bar)出现在输出中。\xc2\xa0\n相比之下,terdon\xe2\x80\x99s 答案会删除每一行\n从匹配的行开始,foo\nup仅包含空格的第一个后续行;\nso第 8 行被删除,但第 9 行和第 10 行仍然存在。

\n\n

这些并不完全是用户所要求的。

\n\n
awk \'/foo/ {suppress=1}\n     /^\\s*$/ && suppress==1 {suppress=2}\n     /[^\\s]/ && suppress==2 {suppress=0}\n     !suppress\' file.php\n
Run Code Online (Sandbox Code Playgroud)\n\n

是。\xc2\xa0 (为了便于阅读,将其分为多行;\nit 可以在一行中全部输入。)\xc2\xa0\n当它看到 时foo,它会进入抑制模式 #1 ( suppress=1)。\xc2\xa0 \n当它在抑制模式 #1 中看到空行时,\nit 会切换到抑制模式 #2。\xc2\xa0\n当它在抑制模式 #2 中看到非空行时,\nit 会切换到模式 0。 \xc2\xa0\n最后,它执行明显的 \xe2\x80\x94 打印未suppress编辑的行。

\n