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 脚本来删除其中一个段落。
假设我想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
然而,就我个人而言,我会使用 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
编辑的行。