我正在尝试从bash脚本中编写一个数据库调用,并且我遇到了一个子shell剥离我的引号的问题。
这是我正在做的事情的骨头。
#---------------------------------------------
#! /bin/bash
export COMMAND='psql ${DB_NAME} -F , -t --no-align -c "${SQL}" -o ${EXPORT_FILE} 2>&1'
PSQL_RETURN=`${COMMAND}`
#---------------------------------------------
如果我使用'echo'打印$ {COMMAND}变量,输出看起来很好:
echo ${COMMAND}
#---------------
psql drupal7 -F , -t --no-align -c "SELECT DISTINCT hostname FROM accesslog;" -o /DRUPAL/INTERFACES/EXPORTS/ip_list.dat 2>&1
#---------------
此外,如果我剪切并粘贴此屏幕输出,它执行得很好。
但是,当我尝试将命令作为子shell调用中的变量执行时,它会给出错误消息。 错误来自psql客户端,以及已从$ {SQL}字符串周围删除引号的效果。 该错误表明psql正试图将sql字符串中的术语解释为参数。
所以看起来字符串和引号是正确组合的,但是在从主脚本执行调用期间,子shell正在解释$ {SQL}变量/字符串周围的引号。
我试图使用各种方法逃避它们:\", \\", \\\", "", \"" '"', \'"\', ... ...
正如你从“尝试一切”的方法中看到的那样,我不是专家,这让我很生气。
非常感谢任何帮助。
Charlie101
答案 0 :(得分:4)
而不是将命令存储在字符串var中,而不是在这里使用BASH数组:
cmd=(psql ${DB_NAME} -F , -t --no-align -c "${SQL}" -o "${EXPORT_FILE}")
PSQL_RETURN=$( "${cmd[@]}" 2>&1 )
答案 1 :(得分:2)
为什么不使用函数?
,而不是评估字符串的内容call_psql() {
# optional, if variables are already defined in global scope
DB_NAME="$1"
SQL="$2"
EXPORT_FILE="$3"
psql "$DB_NAME" -F , -t --no-align -c "$SQL" -o "$EXPORT_FILE" 2>&1
}
然后你可以像下面这样调用你的函数:
PSQL_RETURN=$(call_psql "$DB_NAME" "$SQL" "$EXPORT_FILE")
完全取决于你如何精心制作这项功能。您可能希望在调用(( $# == 3 ))
命令之前检查正确数量的参数(使用psql
之类的内容。)
或者,也许您只是想让它尽可能短:
call_psql() { psql "$1" -F , -t --no-align -c "$2" -o "$3" 2>&1; }
为了捕获为执行调试而执行的命令,您可以在脚本中使用set -x
。这将是函数的内容,包括调用函数(或任何其他命令)时的扩展变量。您可以使用set +x
关闭此行为,或者如果您希望在脚本的整个持续时间内启用此行为,则可以将shebang更改为#!/bin/bash -x
。这样可以在整个脚本中明确echo
来查找正在运行的命令;您只需打开set -x
部分即可。
使用shebang方法的一个非常简单的示例脚本:
#!/bin/bash -x
ec() {
echo "$1"
}
var=$(ec 2)
在使其成为可执行文件或使用bash -x
进行调用后直接运行此脚本会给出:
++ ec 2
++ echo 2
+ var=2
从shebang中删除-x
或调用会导致脚本以静默方式运行。