使用Bash的sed替换文件内容遇报错,求非正则解决方案
解决sed替换多行文本时的"unterminated `s' command"错误
问题场景
尝试用Bash脚本的sed功能替换文件内容,不想使用正则表达式,但执行脚本时出现错误:sed: -e expression #1, char 7: unterminated s' command`
输入内容
<if property="headless"> <VMArg name="-Djava.awt.headless=true"/> </if> <VMArg name="-Dfile.encoding=UTF-8"/> <VMArg name="-Djava.util.logging.config.file=$VDISTDIR/system/conf/logging.properties"/> <VMArg name="-Dlog4j.configurationFile=file:///$VDISTDIR/system/conf/log4j2.yaml"/>
期望输出
<if property="headless"> <VMArg name="-Djava.awt.headless=true"/> </if> This is the replaced text <VMArg name="-Dfile.encoding=UTF-8"/> <VMArg name="-Djava.util.logging.config.file=$VDISTDIR/system/conf/logging.properties"/> <VMArg name="-Dlog4j.configurationFile=file:///$VDISTDIR/system/conf/log4j2.yaml"/>
尝试的错误脚本
#!/bin/bash find='<if property="headless"> <VMArg name="-Djava.awt.headless=true"/> </if> <VMArg name="-Dfile.encoding=UTF-8"/>' replace='<if property="headless"> <VMArg name="-Djava.awt.headless=true"/> </if> <VMArg name="-Dfile.encoding=UTF-8"/>' sed "s/$find/$replace/g" filename.input
错误原因
- 多行文本破坏命令结构:
find和replace变量包含换行符,直接代入sed的s命令时,换行会被解析为命令结束,导致sed认为s命令未完成,触发"unterminated `s' command"错误。 - 分隔符冲突:sed默认用
/作为s命令的分隔符,而文本中存在大量/(比如file:///),会提前截断命令,引发语法错误。 - 替换内容未达标:原脚本的
replace变量没有添加期望的This is the replaced text,无法实现目标输出效果。
解决方案
方案一:直接追加文本(推荐)
不需要替换大块多行文本,精准匹配</if>所在行,在其后插入目标文本即可,这种方式简洁且避免多行处理的问题:
#!/bin/bash sed '/ <\/if>/a\This is the replaced text' filename.input
脚本说明
/ <\/if>/:精确匹配</if>这一行(注意转义/为\/)a\:sed的追加命令,在匹配行的下一行插入指定文本
方案二:多行替换(如需替换整块内容)
改用|作为s命令的分隔符,并将变量中的换行符转义为\n,确保sed正确解析:
#!/bin/bash find='<if property="headless">\n <VMArg name="-Djava.awt.headless=true"/>\n </if>\n\n <VMArg name="-Dfile.encoding=UTF-8"/>' replace='<if property="headless">\n <VMArg name="-Djava.awt.headless=true"/>\n </if>\nThis is the replaced text\n <VMArg name="-Dfile.encoding=UTF-8"/>' sed -e "s|$find|$replace|g" filename.input
脚本说明
- 用
|替代/作为分隔符,避免与文本中的/冲突 - 将变量中的换行符替换为
\n,并使用-e参数确保sed正确解析转义字符
内容的提问来源于stack exchange,提问作者Chetan Potdar
相关产品推荐
相关产品推荐

