PHP有mysql_real_escape_string()
来正确转义可能导致问题的任何字符。模仿BASH的这种功能的最佳方法是什么?
无论如何使用bash做准备好的mysql语句?这似乎是最好的方式。
我的大部分变量都不会(不应该)包含特殊字符,但是我会为用户提供完全的密码自由。它可能包含“和”之类的字符。
我可能正在做多个SQL语句,所以我想创建一个接受参数然后运行语句的脚本。这就是我到目前为止所做的:
doSQL.sh:
#!/bin/sh
SQLUSER="root"
SQLPASS="passwor339c"
SQLHOST="localhost"
SQL="$1"
SQLDB="$2"
if [ -z "$SQL" ]; then echo "ERROR: SQL not defined"; exit 1; fi
if [ -z "$SQLDB" ]; then SQLDB="records"; fi
echo "$SQL" | mysql -u$SQLUSER -p$SQLPASS -h$SQLHOST $SQLDB
以及使用所述命令的示例:
example.sh:
PASSWORD=$1
doSQL "INSERT INTO active_records (password) VALUES ('$PASSWORD')"
如果密码密码中包含单引号,显然会失败。
答案 0 :(得分:11)
在Bash中,printf
可以为您进行转义:
$ a=''\''"\;:#[]{}()|&^$@!?, .<>abc123'
$ printf -v var "%q" "$a"
$ echo "$var"
\'\"\\\;:#\[\]\{\}\(\)\|\&\^\$@\!\?\,\ .\<\>abc123
我会留给你判断这是否足够激进。
答案 1 :(得分:4)
这似乎是使用错误工具的经典案例。
你前面有一个很多的工作来实现bash中mysql_real_escape_string()
完成的转义。请注意,mysql_real_escape_string()
实际上将转义委托给MySQL库,该库考虑了连接和数据库字符集。它被称为“真实”,因为它的前身mysql_escape_string()
没有考虑字符集,并且可能被欺骗注入SQL。
我建议使用具有MySQL库的脚本语言,例如Ruby,Python或PHP。
如果您坚持使用bash,请使用MySQL Prepared Statements语法。
答案 2 :(得分:2)
mysql_real_escape_string()
当然只转义要引用的单个字符串文字,而不是整个语句。您需要明确字符串在语句中的用途。根据{{3}}上的MySQL手册部分,要插入字符串字段,您只需要转义单引号和双引号,反斜杠和NUL。但是,bash字符串不能包含NUL,因此以下内容应该足够了:
#escape for MySQL single string
PASSWORD=${PASSWORD//\\/\\\\}
PASSWORD=${PASSWORD//\'/\\\'}
PASSWORD=${PASSWORD//\"/\\\"}
如果您在LIKE
之后使用字符串,您可能还想要转义%
和_
。
准备好的陈述是另一种可能性。并确保您不要在bash中使用echo -e
。
答案 3 :(得分:1)
无论您使用什么引号,都不能逃脱以下结构:
PASSWORD=$1
doSQL "INSERT INTO active_records (password) VALUES (FROM_BASE64('$(echo -n $PASSWORD|base64)'))"
答案 4 :(得分:0)
这将逃避撇号
a=$(echo "$1" | sed s/"'"/"\\\'"/g)
请注意,虽然mysql_real_escape_string也会转义\ x00,\ n,\ r \ n,\,“和\ x1a。请确保为了完全安全而逃避这些。
要逃脱\ x00,例如:
a=$(echo "$1" | sed s/"\x00"/"\\\'"/g)
稍微努力一下,你可以使用一个sed命令来逃避这些。
答案 5 :(得分:0)
当然,为什么不只使用真实的东西呢?
任意位置的脚本,例如
〜/ scripts / mysqli_real_escape.php
#!/bin/php
<?php
$std_input_data = '';
$mysqli = new mysqli('localhost', 'username', 'pass', 'database_name');
if( ftell(STDIN) !== false ) $std_input_data = stream_get_contents(STDIN);
if( empty($std_input_data) ) exit('No input piped in');
if( mysqli_connect_errno( ) ) exit('Could not connect to database');
fwrite ( STDOUT,
$mysqli->real_escape_string($std_input_data)
);
exit(0);
?>
接下来,从bash终端运行:
chmod +x ~/script/mysqli_real_escape.php`
ln -s ~/script/mysqli_real_escape.php /usr/bin/mysqli_real_escape
全部准备好!现在,您可以在bash脚本中使用
mysqli_real_escape
!
#!/bin/bash
MyString="stringW@#)*special characters"
MyString="$(printf "$MyString" | mysqli_real_escape )"
注意:据我了解,使用"$(cmd ..."$var")"
的命令替换比使用反引号更可取。但是,由于不需要进一步的嵌套,所以两者都应该很好。
进一步注意:在命令替换"$(...)"
中,将创建一个新的引用上下文。这就是为什么变量周围的引号不会弄乱字符串的原因。
答案 6 :(得分:0)
这就是我的做法,my-file.txt
包含空格,换行和引号:
IFS='' content=$(cat my-file.txt)
mysql <flags> -e "update table set column = $(echo ${content@Q} | cut -c 2-) where something = 123"
答案 7 :(得分:-1)
这将有效:
echo "John O'hara" | php -R 'echo addslashes($argn);'
将其传递给变量:
name=$(echo "John O'hara" | php -R 'echo addslashes($argn);')