使用 sed 删除特定模式之前的两行
Posted
技术标签:
【中文标题】使用 sed 删除特定模式之前的两行【英文标题】:Delete two lines before a specific pattern using sed 【发布时间】:2017-10-13 04:47:17 【问题描述】:对 sed 不太熟悉,我正在尝试删除模式前的两行(超时值和空行),然后用更新的超时重新插入两行。
这是我拥有的 yaml 文件的一部分:
- id: phase1
blahblahbal
timeout: 720
- id: phase2
blahblahbalh
timeout: 1800
我正在尝试将第一次超时更新为“900”。
这是我用 grep 完成的:
grep -v "$(grep -B 2 'id: phase2' test.yaml | grep -v 'id: phase2')" test.yaml > test.yaml
然后使用 sed 插入更新的值。这是有效的,但 grep 看起来不太好。有没有办法在模式前用 sed 删除两行?
第一次 sed/grep 后的预期输出:
- id: phase1
blahblahbal
- id: phase2
blahblahbalh
timeout: 1800
预期的最终输出:
- id: phase1
blahblahbal
timeout: 900
- id: phase2
blahblahbalh
timeout: 1800
【问题讨论】:
显示您的预期输出。 相对于模式删除是困难的,当模式遵循需要删除的内容时更是如此。 @JonathanLeffler 该评论有何帮助? 您的预期输出没有删除行?您刚刚更换了号码。那是你真正想要的吗? 这是最终输出。 【参考方案1】:这是我使用 sed 的解决方案:
# Remove above two lines before phase2 id
sed -i ':a;N;s/\n/&/2;Ta;/\n- id\: phase2$/s/.*\n//;P;D' test.yaml
# Add updated timeout
sed -i "/- id\: phase2/ i\\
timeout: 900\\
" test.yaml
【讨论】:
我知道 sed 不仅仅是 s (替代),但我从来没有能够掌握它。虽然,由于 awk 的存在,我的积极性很低...... 大声笑,我刚刚从其他地方复制了第一个 sed。没有得到该命令中实际发生的情况。【参考方案2】:这就是使用 awk (back-replace2.awk
) 的方法:
$1 ~ /timeout:/ lineTimeOut = NR
/^[ \t\r]*$/ lineEmpty = NR
/- id: phase2/
if (lineTimeOut == NR - 2 && lineEmpty == NR - 1)
buf1 = " timeout: 900"
if (NR > 2) print buf1
buf1 = buf2 ; buf2 = $0
END
if (NR >= 2) print buf1
if (NR >= 1) print buf2
记住timeout:
行和空行的行号。因此,可以检查这些行是否恰好出现在与注释模式(此处为- id: phase2
)匹配的行之前/之前的两行。
变量buf1
和buf2
用于进行某种循环缓冲(即每行都回显倒数第三行)。
因此,END
规则对于回显其余输入(循环缓冲区的内容)是必要的。
测试:
$ cat >back-replace2.txt <<EOF
- id: phase1
blahblahbal
timeout: 720
- id: phase2
blahblahbalh
timeout: 1800
EOF
$ awk -f back-replace2.awk back-replace2.txt
- id: phase1
blahblahbal
timeout: 900
- id: phase2
blahblahbalh
timeout: 1800
$
注意事项:
我没有检查边缘情况(例如,是否正确处理了少于 3 行的文件)。
模式匹配和替换可能需要额外的逻辑。我相信提问者能够适当地调整脚本。
【讨论】:
谢谢@Scheff。我也找到了另一种方法(作为答案添加)。以上是关于使用 sed 删除特定模式之前的两行的主要内容,如果未能解决你的问题,请参考以下文章