Gitlab CI中sed命令行为异常:起始注释标签被误删
问题描述
在.gitlab-ci.yml中配置了以下sed命令,用于删除README.md中两个注释标签之间的内容:
- sed -i '/<!-- START_CLIENT_TABLE -->/,/<!-- END_CLIENT_TABLE -->/{//!d}' README.md
README.md原始内容:
# Clients <!-- START_CLIENT_TABLE --> test test2 <!-- END_CLIENT_TABLE -->
本地ash环境执行该命令后,得到预期结果:
# Clients <!-- START_CLIENT_TABLE --> <!-- END_CLIENT_TABLE -->
但在GitLab CI使用的Alpine Linux(ash shell)环境中执行时,起始注释标签会被一并删除,异常结果如下:
# Clients <!-- END_CLIENT_TABLE -->
尝试调整引号、分隔符及转义方式后,CI环境中的命令仍异常,询问该行为异常的原因及解决办法。
问题原因
核心原因是Alpine Linux使用的是BusyBox版本的sed,而本地环境大概率使用的是GNU sed,两者在范围匹配命令的逻辑处理上存在差异:
- GNU sed在处理
/START/,/END/{//!d}时,会将范围的起始行(匹配START的行)和结束行(匹配END的行)排除在//!d的判断之外,仅删除中间的内容。 - BusyBox sed则会将起始行纳入
//!d的检查范围:由于起始行匹配的是START模式,而//!表示“不匹配当前命令的地址模式”,BusyBox sed会误判起始行不符合保留条件,进而将其删除。
解决方案
使用兼容BusyBox sed和GNU sed的命令写法,替换原有的sed命令:
- sed -i -e '/<!-- START_CLIENT_TABLE -->/{:loop;n;/<!-- END_CLIENT_TABLE -->/!{d;b loop}}' README.md
该命令的逻辑:
- 匹配到起始注释标签行后,进入循环标记
loop - 读取下一行(
n) - 如果当前行不是结束注释标签,则删除该行并回到循环标记继续处理(
d;b loop) - 匹配到结束注释标签行时,停止循环并保留该行
这样无论在本地GNU sed环境还是CI的BusyBox sed环境,都能得到预期结果。
内容的提问来源于stack exchange,提问作者Pikkostack
相关产品推荐
相关产品推荐

