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 脚本来删除其中一个段落。
所以说我想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
Run Code Online (Sandbox Code Playgroud)
我怎么可能去做这件事。我想过使用,sed但这似乎只适用于一个衬垫?
sed -i 's/foo//g' file.php
Run Code Online (Sandbox Code Playgroud)
而且我无法为每一行都这样做,因为该段落中的大多数行都不是唯一的!有任何想法吗?
实际上,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)
sed比 terdon\xe2\x80\x99s答案稍微复杂一点:\n
awk \'/foo/ {suppress=1} /^\\s*$/ {suppress=0} !suppress\' file.php\nRun 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\nRun 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\nawk \'/foo/ {suppress=1}\n /^\\s*$/ && suppress==1 {suppress=2}\n /[^\\s]/ && suppress==2 {suppress=0}\n !suppress\' file.php\nRun 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编辑的行。