我正在尝试编写一个命令来对目录中的一批 php 文件进行 perl 替换。我要替换的字符串中有单引号,我无法让它正确地转义 shell。
我尝试回显带有未转义的引号的字符串,以查看 perl 会得到什么:
echo 's/require_once\('include\.constants\.php'\);/require_once\('include\.constants\.php'\);require_once\("\./functions/include\.session\.inc\.php"\);/g'
并且结果中没有单引号:
s/require_once\(include.constants.php\);/require_once\(include.constants.php\);require_once\("\./functions/include\.session\.inc\.php"\);/g
但是,当我尝试逃避单引号时:
echo 's/require_once\(\'include\.constants\.php\'\);/require_once\(\'include\.constants\.php\'\);require_once\("\./functions/include\.session\.inc\.php"\);/g'
我收到完成命令的提示:
>
我希望它解析的是:
s/require_once\('include.constants.php'\);/require_once\('include.constants.php'\);require_once\("\./functions/include\.session\.inc\.php"\);/g
我究竟做错了什么?
答案1
在外面使用"
而不是,那么您只需要在表达式内部转义两个。'
"
echo "s/require_once\('include.constants.php'\);/require_once\('include.constants.php'\);require_once\(\"\./functions/include\.session\.inc\.php\"\);/g"
答案2
单引号字符串内不会发生任何类型的扩展或求值,甚至反斜杠转义也不会。正如 Nifle 和 canen 所发布的,请改用双引号,并转义双引号而不是单引号。但是,您只需要为了 shell 的利益而转义它们。如果您打算s///
直接在 perl 脚本中使用它,则无需转义,因为您通常不会将其括s///
在引号中。
此外,s///
由于替换字符串中有分隔符,因此操作将失败/
。可以使用反斜杠转义以下斜杠/functions/include
:
s/require_once\('include.constants.php'\);/require_once\('include.constants.php'\);require_once\("\.\/functions\/include\.session\.inc\.php"\);/g
或选择不同的分隔符:
s@require_once\('include.constants.php'\);@require_once\('include.constants.php'\);require_once\("\./functions/include\.session\.inc\.php"\);@g
答案3
为什么不使用双引号?
"s/require_once\('include.constants.php'\);/require_once\('include.constants.php'\);require_once\("\./functions/include\.session\.inc\.php"\);/g"
答案4
您使用单引号对单引号进行转义。例如,假设您想要使用以下消息进行 git 提交:已更新 BaseActiveRecord 的 save() 方法。
为此,请运行以下命令(请注意,我使用单引号转义了单引号)。
git commit -m 'Updated BaseActiveRecord''s save() method.'
您还可以使用双引号(而不是转义单引号)来实现您的目标:
git commit -m "Updated BaseActiveRecord's save() method."
但是,请注意命令行上的双引号会导致某些内容扩展(即 $vars)。希望这能有所帮助。