sed工具单引号、双引号包裹的参数文本中如何正确插入换行符
双引号包裹sed参数时正确插入多行内容的方法
问题根因
shell对单引号、双引号包裹内容的解析规则存在差异:
- 单引号属于强引用,包裹的所有字符会原样传递给sed命令,行尾用于标记sed续行插入的
\不会被提前处理,sed可以正常识别多行插入规则,输出符合预期。 - 双引号属于弱引用,shell会预先解析包裹内容中的特殊字符:行尾的
\会被shell识别为自身的行续接标记,在参数传递给sed之前就被移除,最终sed收到的是所有行被拼接成一整段的内容,因此会出现换行、行首缩进丢失,所有插入内容挤在同一行的异常。
可行解决方案
方案1:双引号内对续行反斜杠做转义(跨sed版本兼容)
在每个续行行尾写两个反斜杠\\,第一个反斜杠用来告诉shell:后面的反斜杠是普通字符,要原样传给sed。最终sed收到的内容和单引号版本完全一致,既保留换行、缩进,也能正常解析双引号内的shell变量:
# 可直接在插入内容中引用shell变量,例如下方的$insert_content sed "/target line/ i\\ inserted line1;\\ inserted line2;\\ inserted line3;\\ $insert_content" file.txt
这个写法在GNU sed(Linux系统默认)、BSD sed(macOS/FreeBSD系统默认)下都能正常运行。
方案2:单双引号混拼(写法最贴近原单引号版本)
不需要变量展开的sed命令固定部分用单引号包裹,需要引用shell变量的部分单独拆出来用双引号包裹,既避免了双引号下反斜杠被转义的问题,又能正常读取变量值,不容易写错:
sed '/target line/ i\ inserted line1;\ inserted line2;\ inserted line3;\ '"$your_shell_var" file.txt
方案3:GNU sed下用\n显式标记换行
如果使用Linux环境默认的GNU sed,可以直接在插入内容中用\n标记换行位置,不需要写续行反斜杠,写法更紧凑:
sed "/target line/ i\ inserted line1;\n inserted line2;\n inserted line3;" file.txt
注意这个写法不兼容BSD sed,跨平台场景不推荐使用。
内容的提问来源于stack exchange,提问作者taoistmiao
相关产品推荐
相关产品推荐

