Ubuntu bash下按行号用含特殊字符的字符串替换文件指定整行
问题根源
- 单引号包裹的内容不会触发Bash变量展开,你使用
'${THELINENUMBER}'这类写法时,变量根本没有被替换为实际的行号值,sed直接收到的是${THELINENUMBER}字符串,语法不合法。 - 即使正确用双引号展开变量,NEWLINE中如果包含sed替换语法的保留字符(分隔符、
&、\、换行符等),会被sed解析为语法关键字,而非普通文本内容,因此仅更换分隔符无法解决所有特殊字符问题。
方案1:使用sed(需提前转义特殊字符)
首先对NEWLINE中sed的保留字符做转义处理,我们选择#作为分隔符,仅需转义#、\、&三类字符即可:
# 转义NEWLINE中的sed特殊字符 ESCAPED_NEWLINE=$(sed 's/[#&\]/\\&/g' <<< "$NEWLINE") # 执行行替换 sed -i "${THELINENUMBER}s#.*#${ESCAPED_NEWLINE}#" after.txt
注意:该方案仅适用于NEWLINE为单行文本的场景,如果NEWLINE包含换行符需要额外处理。
方案2:使用awk(更稳妥,无需转义)
awk支持直接传入字面量变量,不需要担心特殊字符被解析为语法,更适合处理含任意特殊字符的文本替换场景:
awk -v target_line="${THELINENUMBER}" -v new_content="${NEWLINE}" ' NR == target_line {print new_content} NR != target_line {print $0} ' after.txt > tmp_file && mv tmp_file after.txt
该方案不需要对NEWLINE做任何转义处理,只要是单行内容都可以正确替换,不会出现语法冲突。
额外说明
Ubuntu 18.04自带的是GNU sed,上述sed命令的-i参数不需要额外加空备份后缀,可直接使用。
内容的提问来源于stack exchange,提问作者robotsfoundme
相关产品推荐
相关产品推荐

