您正在将此字符串传递给system
,因此您的外壳(已格式化以提高可读性):
/usr/bin/drush
-r /var/www/html/mysite/web
-u sites.admin
--yes sql-query '
update node_revisions
set body = REPLACE(body,'</div>',
'<?php
$contact_us_node = abc_drupal_node_load(NULL, 'my_group');
if (isset($contact_us_node->field_contact_us_message_body)) {
echo $contact_us_node->field_contact_us_message_body[0]['value'] . "<br />";
}
?></div>'
)
WHERE nid=123'
为什么?Perl 的双引号字符串通过删除反斜杠来忽略未知的转义。例如:"\(" eq "("
。这意味着当 shell 看到该命令时,所有这些反斜杠都不见了!让我们看看 shell 实际看到的是什么“字符串”:
/usr/bin/drush
-r
/var/www/html/mysite/web
-u
sites.admin
--yes
sql-query
'update node_revisions set body = REPLACE(body,'
</div>
','
<?php $contact_us_node = abc_drupal_node_load(NULL,
'my_group'
);if (isset($contact_us_node->field_contact_us_message_body)) {echo $contact_us_node->field_contact_us_message_body[0][
'value'
] .
"<br />"
;}?></div>
') WHERE nid=123'
这绝对不是你想要的。我们有三个级别的转义:
- Perl 字符串
- 贝壳
- SQL
- (PHP 代码,但这里没有使用任何转义符)
我们如何解决这个问题?我们可以通过直接使用 Perlexec
命令而不将其传递给 shell 来删除 shell 级别。为此,我们使用该命令的列表形式:
system(
$drushcmd,
'-r', $drupalroot,
'-u', 'sites.admin',
'--yes',
'sql-query',
"update node_revisions set body = REPLACE\(body,\'</div>\',\'<?php \$contact_us_node = abc_drupal_node_load\(NULL, \'my_group\'\);if \(isset\(\$contact_us_node->field_contact_us_message_body\)\) {echo \$contact_us_node->field_contact_us_message_body[0][\'value\'] . \"<br />\";}?></div>\'\) WHERE nid=123'",
) == 0 or die "$drushcmd failed: $?";
啊,是的,这样更好。我们可以通过使用带有替代分隔符的单引号字符串来进一步消除在 Perl 代码中转义的需要:
q#update node_revisions set body = REPLACE(body,'</div>','<?php $contact_us_node = abc_drupal_node_load(NULL, 'my_group');if (isset($contact_us_node->field_contact_us_message_body)) {echo $contact_us_node->field_contact_us_message_body[0]['value'] . "<br />";}?></div>') WHERE nid=123'#
我们现在已经消除了 Perl 和 shell 的转义级别,所以只剩下 SQL。