寻找一种优雅的方法,在脚本结束时bash
清理生成的文件,如果:
- 要删除的行下面的行的第一个字符是
#
或者 #
是文件中最后一行的第一个字符。
文件可能看起来像这样(参考行号在[]
但在不是在文件本身中):
[1] # foo
[2] bar1
[3] bar2
[4] bar3
[5] # foob
[6] #ar
[7] ar1
[8] ar2
[9] ar3
[10] #
在上面的示例中,我想删除第 5 行和第 10 行。我不希望任何以 开头的行后面#
跟着以 开头的行,#
并且我不希望文件的最后一行以 开头#
。
编辑:预期输出:
[1] # foo
[2] bar1
[3] bar2
[4] bar3
[5] #ar
[6] ar1
[7] ar2
[8] ar3
bash
边走边教自己极好的被sed
和awk
语法混淆,但我怀疑它们就是这里的答案。
答案1
我思考你想要的是
sed -e '${/^#/d}' -e '$!N;/^#.*\n#/D' -e 'P;D' file
${/^#/d}
地址最后一行$
;如果匹配^#
则删除它$!N
...P;D
维持滚动的两行缓冲区/^#.*\n#/D
#
如果模式开头和换行符后面都有 a ,则删除到换行符并开始新的循环
答案2
sed
您的要求可以如图所示进行编码。
sed -e '
/^#/!b
$d;N
/\n#/D
' file
任何不感兴趣的行都会被发送到标准输出,这意味着打印:
/^#/!b
有趣的一行是以 a 开头的
#
最后一行恰好有趣的被删除:
$d
请注意,无意义的行不能出现在第二个 sed 代码行中。
如果感兴趣的行不是文件的最后一行,我们将下一行附加到它:
N
如果下一行也很有趣,请删除上一行并使用现有模式空间转到 sed 脚本的顶部:
/\n#/D
您应该参阅 sed 手册以获取有关所使用的各种 sed 命令的详细信息。
答案3
您可以使用sed
多线技术
sed -E 'N;s/(^#.*)(#.*)/\2/;${s/(.*)(#.*)/\1/}' file
N
命令将 anewline
和下一行追加到模式空间。
对于带有模式的行^#.*#.*
删除第一行。
${}
对于最后一行,检查模式是否.*#.*
匹配,删除最后一部分。
答案4
sed -n '/^#/{:a;h;n;//b a;H;g;};p' file
选项-n
禁用自动打印,行将通过p
操作打印。/^#/{ ... }
– 在以 开头的行上#
,执行一组操作。:a
...b a
设置一个循环,在该循环中:
h
用模式空间替换保持空间(即将当前行保存到缓冲区)。n
将下一行输入读入模式空间(或退出,没有更多输入)。//b a
–如果模式空间匹配则b
牧场到。在 中,空正则表达式是 的简写。:a
/^#/
sed
apply the last used regex
循环完成后:H;g
– 将当前模式空间追加到保持空间,并将模式空间替换为保持空间。p
最后打印循环的结果以及所有其他非行#
。
#
结果:仅打印任何一组行中的最后一行,#
末尾之前不打印任何行。
# foo
bar1
bar2
bar3
#ar
ar1
ar2
ar3