使用 sed 删除所有以模式 b 开头的行,然后是模式 a 的行
Posted
技术标签:
【中文标题】使用 sed 删除所有以模式 b 开头的行,然后是模式 a 的行【英文标题】:Use sed to delete all lines starting with pattern b after line with pattern a 【发布时间】:2021-01-08 01:23:13 【问题描述】:给定一个类似的文件:
first line
second line DELETE ME
- third line
- fourth line
fifth line
sixth line DELETE ME
seventh line
- eighth line
还有模式 a (DELETE ME
) 和模式 b ([[:blank:]]*-
),我只想保留
first line
fifth line
seventh line
- eighth line
或者换句话说,我想删除包含模式 a 的每一行以及所有以模式 b 开头的直接跟随行>.
到目前为止,我只满足了部分但不是全部要求:
sed '/DELETE ME/N;s/^[[:blank:]]*-//;d;'
这应该删除所有包含 a 的行以及包含 b 的连续行。
【问题讨论】:
您是否致力于 sed,或者其他工具是否可以接受? 这是一个 yaml 文件吗?sed '/DELETE ME/:a;N;s/\n[[:blank:]]*-.*//;ta;!P;D' file
我的最终目标是:我有一个 gitlab-ci 模板存储库,其中包含许多 gitlab-ci yaml 文件,使用(可能嵌套)包含。现在我想为该存储库创建一个 gitlab-ci 文件,根据included CI lint tool(API)检查包含的所有文件的有效性。我发现this solution 用于稍微不那么通用的情况,但想使其适应我的用例. --- @WiktorStribiżew 似乎可行,您介意添加解释并提交作为答案吗?
【参考方案1】:
使用 GNU sed
,您可以使用
sed '/DELETE ME/:a;N;s/\n[[:blank:]]*-.*//;ta;!P;D' file
见online sed
demo:
s='first line
second line DELETE ME
- third line
- fourth line
fifth line
sixth line DELETE ME
seventh line
- eighth line'
sed '/DELETE ME/:a;N;s/\n[[:blank:]]*-.*//;ta;!P;D' <<< "$s"
输出:
first line
fifth line
seventh line
- eighth line
详情
/DELETE ME/
- 查找所有包含 DELETE ME
字符串的行
:a;N;s/\n[[:blank:]]*-.*//;ta;!P;D
- 如果找到匹配 DELETE ME
的行,则进入此块:
:a
- a
标签标记当前位置
N
- 将带有 \n
开头的下一行读入模式空间
s/\n[[:blank:]]*-.*//
- 查找并删除换行符、0+ 个空白字符、-
和字符串的其余部分
ta
- 如果发生替换,sed
会转到标有 a
的位置
!P
- 否则,打印模式空间内容直到第一个换行符(即打印第一行)
D
- 删除模式空间内容直到第一个新行,即删除模式空间内的第一行,并使用生成的模式空间重新开始循环,而不读取新的输入行。
【讨论】:
【参考方案2】:虽然 yaml 文件应该由理解它们的工具解析,但由于 OP 使用了sed
,所以我在这里提出了awk
解决方案。请您尝试以下操作。在链接https://ideone.com/WNROOt 中编写和测试,并且仅使用显示的示例进行测试和编写。
awk '
!/^ +/
foundDel=""
/DELETE ME/
foundDel=1
next
foundDel && /^ +/
next
1
' Input_file
注意:如果您想将输出保存到 Input_file 本身,请附加 > temp && mv temp Input_file
【讨论】:
【参考方案3】:这可能对你有用(GNU sed):
sed -n '/DELETE ME/:a;n;/^\s*-/ba;p' file
通过设置选项-n
关闭隐式打印。
遇到包含DELETE ME
的行时,形成一个循环以获取下一行,如果该行以一些空格开头,后跟-
,则重复循环。
否则,打印所有其他行。
【讨论】:
这会在我的设置中产生sed: unterminated
。
试试'/DELETE ME/:a;n;/^\s*-/ba;;p'
以上是关于使用 sed 删除所有以模式 b 开头的行,然后是模式 a 的行的主要内容,如果未能解决你的问题,请参考以下文章
自建yum仓库;编译安装http2.4 ;删除/etc/fstab文件中所有以#开头的行;sed 取本机的IP地址;sed命令取目录名