You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell中sed替换文件cmd行结果异常,寻求解决办法

问题描述

我有一个sample.txt文件,内容如下:

# sample.txt
adc=lalalala
cmd="echo hihi && echo yoyo"
cda=lolololo

我希望修改其中的cmd行,编写了如下脚本:

old=`cat ./sample.txt|grep cmd`
app=' && echo dudu"'

new=${old:0:-1}${app}

sed -i "s/${old}/${new}/g" ./sample.txt

期望得到的结果是:

adc=lalalala
cmd="echo hihi && echo yoyo && echo dudu"
cda=lolololo

但实际执行后得到异常结果:

adc=lalalala
cmd="echo hihi cmd="echo hihi && echo yoyo"cmd="echo hihi && echo yoyo" echo yoyo cmd="echo hihi && echo yoyo"cmd="echo hihi && echo yoyo" echo dudu"
cda=lolololo

我也尝试了使用sed -i "s#${old}#${new}#g" ./sample.txt,但结果没有区别,希望能得到帮助。


问题原因

你的脚本出问题的核心是old变量里包含了sed的元字符——比如&。在sed的替换语法中,&代表匹配到的整个内容。你的old值是cmd="echo hihi && echo yoyo",里面的&&会被sed解析成两个“匹配内容占位符”,替换时每个&都会被替换成原来的old内容,直接导致字符串重复。

另外,变量里的双引号也会干扰sed的语法解析,进一步加剧混乱。


解决方案

不需要先提取整行再替换,直接用sed定位cmd行修改更简单可靠:

方案1:直接在cmd行末尾引号前追加内容

sed -i 's/^\(cmd=".*\)"$/\1 && echo dudu"/' sample.txt

解释:

  • ^ 匹配行开头,确保只修改以cmd=开头的行
  • \(cmd=".*\) 捕获cmd="到最后一个引号前的所有内容(用括号分组,后续用\1引用)
  • "$ 匹配行末尾的引号
  • \1 && echo dudu" 把捕获的内容加上要追加的部分,再补上闭合引号

方案2:用变量控制追加内容(动态修改场景)

如果需要动态指定要追加的内容,可以用变量实现:

append=' && echo dudu'
sed -i "s/^\(cmd=\".*\)\"$/\1${append}\"/" sample.txt

方案3:直接替换cmd的完整值(非追加场景)

如果是要直接替换cmd的整个值,而非追加内容,可以用:

sed -i 's/^cmd=".*"/cmd="echo hello world"/' sample.txt

验证结果

执行上述任意一个方案后,sample.txt的内容会符合预期:

# sample.txt
adc=lalalala
cmd="echo hihi && echo yoyo && echo dudu"
cda=lolololo

内容的提问来源于stack exchange,提问作者furynerd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 04:50:24