如何用sed替换config.yml中冒号左侧的所有连字符为下划线?
解决YAML文件中仅替换冒号左侧连字符的问题
我明白你的困扰——想只把config.yml里冒号(:)左侧的连字符(-)换成下划线(_),但之前的sed命令要么把整行的连字符都替换了,要么没精准命中目标。我来帮你拆解问题,给出正确的解决方案。
先分析你之前的命令为什么不对
第一个命令:
sed '/.*: /s/-/_/g' config.yml
这个命令的逻辑是:先匹配所有包含:的行,然后在整行范围内全局替换连字符。这就导致冒号右侧的内容(比如config/project-scratch-def.json里的-)也被替换了,显然不符合你的需求。第二个命令:
sed '/^[^:]*:/s/-/_/g' config.yml
你试图用^[^:]*:匹配冒号左侧的内容,但sed的替换默认是作用于整行的,哪怕你用了行首匹配的条件,替换操作还是会覆盖整行的连字符,所以依然会修改冒号右侧的内容。
正确的sed解决方案
我们需要精准限定替换范围:只处理每行第一个冒号左侧的所有连字符。这里分两种场景给出命令:
场景1:使用GNU sed(Linux系统默认)
GNU sed支持e选项,可以把替换后的内容作为命令执行,写法更简洁直观:
sed -E 's/^([^:]*)/echo "\1" | tr - _/e' config.yml
- 逻辑说明:
^([^:]*)捕获每行从开头到第一个冒号的所有内容echo "\1" | tr - _把捕获到的内容通过tr命令将-替换为_e选项让sed执行这个替换后的命令,最终输出处理后的行
场景2:POSIX兼容sed(跨平台通用)
如果需要在不支持GNU sed特性的环境(比如BSD/macOS)运行,可以用循环替换的方式:
sed -e ':loop' -e 's/^([^:-]*)-([^:]*:)/\1_\2/' -e 't loop' config.yml
- 逻辑说明:
:loop定义一个循环标签,用于重复替换操作s/^([^:-]*)-([^:]*:)/\1_\2/匹配行首到第一个-的内容,以及-之后到冒号的内容,将-替换为_t loop如果刚才的替换成功(说明还有未替换的-),就跳回loop标签继续替换,直到冒号左侧没有-为止
效果验证
假设你的config.yml里有这样一行:
my-config-key: config/project-scratch-def.json
执行上述命令后,会变成:
my_config_key: config/project-scratch-def.json
完美实现了只替换冒号左侧连字符的需求!
内容的提问来源于stack exchange,提问作者Wade
相关产品推荐
相关产品推荐

