echo "sed -i 's/NULL/\\N/g' ".$_REQUEST['para'].".sql";
以上陈述有效。但是当我在这样的执行官中使用它时失败了......
exec("sed -i 's/NULL//\/\/\N/g' ".$_REQUEST['para'].".sql");
答案 0 :(得分:5)
你应该使用反斜杠来逃避反斜杠,而不是使用正斜杠,如下所示:
exec("sed -i 's/NULL/\\\\N/g' ".$_REQUEST['para'].".sql");
编辑我写的答案没有看代码实际上做了什么。不要这样做,因为$_REQUEST['para']
可以是用户想要的任何内容,可以用于code injection。正如另一个答案所示,使用PHP函数。
答案 1 :(得分:3)
虽然这完全取决于你,但我的建议是不要不必要地调用系统命令。在PHP中,您可以使用preg_replace()来执行sed。
的功能preg_replace("/NULL/","\\N",file_get_contents("$_REQUEST['para']"."sql") )
答案 2 :(得分:1)
基于ghostdog的想法,这里的代码实际上会做你想要的(他发布的原始代码实际上没有读取文件的内容):
//basename protects against directory traversal
//ideally we should also do a is_writable() check
$file = basename($_REQUEST['para'].".sql");
$text = file_get_contents($file);
$text = str_replace('NULL', '\\N', $text); //no need for a regex
file_put_contents($file, $text);
然而,诚然,如果有问题的文件超过几兆,这是不可取的,因为整个文件将被读入内存。你可以用块读取它,但这会变得更复杂:
$file = basename($_REQUEST['para'].".sql");
$tmpFile = tempnam("/tmp", "FOO");
$in = fopen($file, 'r');
$tmp = fopen($tmpFile, 'w');
while($line = fgets($in)) {
$line = str_replace('NULL', '\\N', $line);
fputs($tmp, $line);
}
fclose($tmp);
fclose($in);
rename($tmpFile, $file);
如果文件是100+ meg,老实说,像你一样直接调用sed会更快。当谈到大文件时,尝试使用其等效的PHP重现像sed / grep这样的工具的开销是不值得的。但是,如果您打算这样做,至少需要采取一些措施来保护自己:
采取一些基本步骤来保护amnom的代码:
$file = basename($_REQUEST['para'].".sql");
if(!is_writable($file))
throw new Exception('bad filename');
exec("sed -i 's/NULL/\\\\N/g' ".escapeshellarg($file));
/etc/passwd; rm -rf /; #
,您最终会得到命令sed 's/blah/blah/' /etc/passwd; rm -rf /; #.sql
。应该清楚的是,虽然这个确切的命令可能不起作用,但找到一个实际上是微不足道的命令。