sed命令引号转义疑问:单双引号为何表现不一致?
Shell引号嵌套解析导致的sed命令报错问题解析
核心规则先明确
- 单引号:内部所有字符原样保留,Shell不会解析任何特殊符号(转义符、括号、变量等),直到遇到配对的单引号才闭合。
- 双引号:内部会解析变量、命令替换和部分转义符(比如
\"、\$),但普通空格、括号等按普通字符处理,遇到配对的双引号才闭合。
逐个拆解你的命令情况
1. 正常工作的基础命令
echo "earth" | sed 's/\(ear\)$/\1md/g'
sed的正则脚本用单引号包裹,Shell不会解析里面的\(ear\)分组标记和\1反向引用,这些符号直接传给sed,自然能正确完成替换。
2. 报错的命令一:外层双引号嵌套双引号
sh -c "echo "earth" | sed "s/\(ear\)th$/\1md/g""
Shell解析时,外层双引号从第一个"开始,遇到echo后面的第二个"就直接闭合了。剩余内容变成:
earth" | sed "s/\(ear\)th$/\1md/g""
这里的(被Shell当作子shell的特殊符号,但没有对应的闭合),直接触发语法错误:sh: 1: Syntax error: "(" unexpected。
3. 报错的命令二:外层单引号嵌套单引号
sh -c 'echo "earth" | sed 's/\(ear\)th$/\1md/g''
Shell解析外层单引号时,从第一个'开始,遇到sed后面的第二个'就闭合了。剩余内容变成:
s/\(ear\)th$/\1md/g''
同样,(被Shell当作特殊符号却没有配对的),导致语法错误。
4. 正常工作的命令一:外层单引号嵌套双引号
sh -c 'echo "earth" | sed "s/\(ear\)th$/\1md/g"'
外层单引号完整包裹整个命令字符串,内部的双引号不会被Shell解析(单引号内所有字符原样保留),整个命令echo "earth" | sed "s/\(ear\)th$/\1md/g"被完整传给sh -c执行。子Shell解析sed的双引号脚本时,\(ear\)和\1里的\不是Shell需要转义的字符,所以这些符号原样传给sed,正则规则正常生效。
5. 正常工作的命令二:外层双引号嵌套单引号
sh -c "echo "earth" | sed 's/\(ear\)th$/\1md/g'"
外层双引号包裹时,内部的单引号是普通字符,不会触发外层双引号的闭合。整个命令echo "earth" | sed 's/\(ear\)th$/\1md/g'被完整传给sh -c执行。sed的脚本用单引号包裹,内部内容完全原样传递,替换逻辑正常运行。
内容的提问来源于stack exchange,提问作者林朔明-Lin_Shuoming
相关产品推荐
相关产品推荐

