感觉这个问题之前就应该在这里回答过,但我的搜索还没有找到确切的案例。
我有一个文件(实际上是一个 hosts 文件),里面有一个标记行。我有一些脚本可以添加和删除标记行前面的行。
但存在删除过程会留下添加过程创建的空白行的风险。
所以我想要一种方法来删除文件中标志行之前的所有空白行。
感觉这应该是可能的sed
,但我发现的在线示例不包括这种情况(讽刺的是,它们包括相反的情况 - 在匹配行之前添加一个空白行)
有没有简单的方法可以做到这一点?
不一定非要使用sed
,任何其他标准文本处理工具也可以。
最好进行就地编辑,但如果确实有必要,可以复制到临时文件,然后再复制回来。
示例输入(无法发布精确数据)
10.8.7.6 static-host1
10.8.7.7 static-host2
10.8.8.5 static-host3
10.8.8.6 static-host4
# Start of dynamic section
10.9.9.8 dynamic-group1-host1
10.9.9.9 dynamic-group1-host1
10.9.8.7 dynamic-group2-host1
10.9.8.8 dynamic-group2-host2
# End of dynamic section
10.10.11.12 static-host5
10.10.11.13 static-host6
10.10.11.17 static-host7
10.10.11.18 static-host8
示例输出
10.8.7.6 static-host1
10.8.7.7 static-host2
10.8.8.5 static-host3
10.8.8.6 static-host4
# Start of dynamic section
10.9.9.8 dynamic-group1-host1
10.9.9.9 dynamic-group1-host1
10.9.8.7 dynamic-group2-host1
10.9.8.8 dynamic-group2-host2
# End of dynamic section
10.10.11.12 static-host5
10.10.11.13 static-host6
10.10.11.17 static-host7
10.10.11.18 static-host8
对于任何解决方案来说,假设要删除的空格之前的最后一行总是以相同的模式开头是合理的,通常是 RFC1918 地址(例如 10. 或 192.168.)
对于另一条评论,是的,空行对于可读性来说是必要的,这就是为什么我的脚本在添加的节之间添加了空行。删除节时,我可以删除“该节第一行之前的任何空行”,但这会引发同样的问题——删除与模式匹配的行之前的一个或多个空行。
(希望很明显)全面删除文件中的所有空行是不可接受的。
解决方案
解释
: load
和之间的片段b load
是一个循环,它将 (N
) 行追加到模式空间,而整个模式空间由“空”行组成:来自space
字符类的字符(在 POSIX 语言环境中,space
字符类恰好包含 <space>、<form-feed>、<newline>、<carriage-return>、<tab> 和 <vertical-tab>;在您的语言环境中可能包含更多字符)。一旦出现不属于该字符类的字符space
,循环就会停止追加,脚本继续执行。换句话说,脚本会将行加载到模式空间中,直到出现非“空”行或输入结束。此时,模式空间就是一段包含零个或多个“空”行的片段,后面跟着最多一个非“空”行。
代码行用
# End of dynamic section
空内容替换(s
)模式空间中的初始“空”行,当且仅当最后加载的行恰好是# End of dynamic section
并且它不是唯一加载的行。最后
sed
打印结果模式空间并开始一个新的循环(如果尚未结束输入),因为这是它的默认行为。笔记
如果您希望脚本检测到真正的空行,则只需将 each 替换
[[:space]]
为 即可。或者,使用或 也是\n
合理的(POSIX 语言环境中只包含 <space> 和 <tab>,但您的语言环境中可能包含更多字符)。选择适合您需求的选项。[ \t\n]
[[:blank:]\n]
blank
每条线都是
# End of dynamic section
独一无二的。