这个命令:
echo '$$foo=bar' | sed -E "s/(\$\$foo=).*/\1$(echo hello)/"
输出:
$$foo=bar
如果我将sed
' 引号更改为单引号并将命令括在双引号中:
echo '$$foo=bar' | sed -E 's/(\$\$foo=).*/\1'"$(echo hello)"'/'
它输出所需的结果:
$$foo=hello
所以我想问题在于扩展的正则表达式和引号,除非我遗漏了一些明显的东西。
sed
在命令替换中连接单引号和双引号是好习惯吗 (sed 's/foo/'"$(command)"'/'
)?如何
sed
使用扩展正则表达式转义双美元符号?
$
POSIX对基本正则表达式和扩展正则表达式的解释方式有不同的说法:基本正则表达式 (BRE):
扩展正则表达式 (ERE):
结论:在 BRE 中,
$
字符匹配自身,除非它是表达式或子表达式的最后一个字符(在这种情况下,它将(子)表达式锚定到行尾)。在 ERE 中,$
角色总是锚定在行尾。当你使用
您的 ERE(因为您使用
-E
)是($$foo=).*
并且此表达式永远不会匹配(上面的 POSIX 文本包含e$f
类似的示例)。你的命令
$$foo
使用将匹配文字字符串的 BRE ,$$foo
因为$
字符不在表达式的末尾。$
要匹配扩展正则表达式中的单个字符,请使用\$
or[$]
。要在双引号字符串中对 shell 进行转义,请使用\\\$
(转义的反斜杠后跟转义的美元符号)或[\$]
,即或者
(反斜杠 in
\1
不需要转义,因为如果后跟美元符号、反引号、双引号、另一个反斜杠或换行符,反斜杠仅充当双引号字符串中的转义字符;所以 the\1
是文字,而不是转义的1
;参考在这里)。简短的答案:
您可以单引号需要单引号的位(并将其与包含您的 shell 扩展的双引号字符串连接),或者您转义需要在单个双引号字符串中转义的内容。这是一个品味问题。我更关心在表达式中使用命令替换,因为这是一个代码注入漏洞,除非您完全控制插入的字符串。
\\\$
或[\$]
在双引号字符串中。\$
或[$]
在单引号字符串中。