Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在子shell执行调用期间,在变量保留字符串中转义引号时出现问题_Bash_Shell_Escaping - Fatal编程技术网

Bash 在子shell执行调用期间,在变量保留字符串中转义引号时出现问题

Bash 在子shell执行调用期间,在变量保留字符串中转义引号时出现问题,bash,shell,escaping,Bash,Shell,Escaping,我试图从bash脚本中编写一个数据库调用,但是我遇到了一个问题,子shell将我的引用剥离掉了 这是我正在做的事情的核心 #--------------------------------------------- #! /bin/bash export COMMAND='psql ${DB_NAME} -F , -t --no-align -c "${SQL}" -o ${EXPORT_FILE} 2>&1' PSQL_RETURN=`${COMMAND

我试图从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}
屏幕输出:- 另外,如果我剪切并粘贴这个屏幕输出,它的执行也很好

但是,当我尝试在子shell调用中作为变量执行该命令时,它会给出一条错误消息。 该错误来自psql客户端,大意是从${SQL}字符串周围删除了引号。 该错误表明psql试图将sql字符串中的术语解释为参数

因此,字符串和引号的组合似乎是正确的,但是${SQL}变量/字符串周围的引号在从主脚本执行调用期间由子shell进行解释

我试着用各种方法来逃避它们:
\”、\\”、\\\”、“、\”、\”、\“\”、…
正如你从我的“全力以赴”方法中所看到的,我不是专家,这让我发疯

任何帮助都将不胜感激


Charlie101

与其将命令存储在字符串变量中,不如在此处使用BASH数组:

cmd=(psql ${DB_NAME} -F , -t --no-align -c "${SQL}" -o "${EXPORT_FILE}")
PSQL_RETURN=$( "${cmd[@]}" 2>&1 )

与其计算字符串的内容,为什么不使用函数呢

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")
函数的详细程度完全取决于您。在调用
psql
命令之前,您可能希望检查参数的正确数量(使用类似
($#==3))

或者,您可能更愿意将其尽可能简短:

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
会导致脚本无声运行。

你好,anubhava。这非常有效,响应速度也非常快。你的方法显然比使用字符串要好,但我对shell数组一无所知。因此我很沮丧。再次感谢。Charlie101。不客气,很高兴它成功了。如果你可以点击我答案左上角的勾号,将答案标记为已接受。在这种情况下,当一个函数更好地表达了你的意思,更具可移植性且不难编写时,为什么要使用数组?@user108168,仅供参考,如果你想以这种方式捕获数组的内容,你可以将其粘贴回command行并保证它的工作方式与
“${cmd[@]}”
相同,即:
printf“%q'”${cmd[@]}"; echo
——如果没有
printf“%q”
和引号,您将得到的并不总是保证在运行时与命令的行为完全相同。嗨,Tom Fenech。谢谢你的回复。你的回答也很有效。我相信你知道。我喜欢这样一个事实,那就是它很好,很普通,也可以做得很简单。很好,很容易理解。有没有一种简单的方法可以捕获函数的实际命令行输出,这样我就可以在错误陷阱中与$PSQL_返回消息一起使用它?如果从命令中删除重定向,它应该将输出保存到变量中。这就是你想要的吗?嗨,汤姆,如果你是指2>&1,那么就不是了。我确信你知道这是在将标准错误重定向到标准输出,这样这两个错误都将被分配给变量,如:PSQL\u RETURN=$(call\u PSQL)。但这并没有告诉我函数的确切命令调用是什么。当然,我可以查看代码,但是很容易忽略一些小问题,除非在complete命令中打开输入变量。对于anubhava的解决方案,我可以使用:${cmd[@]}获取命令和返回变量以获取执行后输出。是否存在${cmd[@]}的等效值?感谢Charlie101Hi Tom Fenech,因为上面的要求,我将标记anubhava作为解决方案。我认为您的解决方案通常是一个非常整洁和清晰的通用解决方案,但我需要捕获准确的命令输出以进行调试。谢谢你的帮助。我相信我会在其他地方使用它。现在我明白了您的意图,我编辑了我的答案,向您展示了如何以相同的方式使用函数。我建议您阅读,因为它包含了一些关于这个主题的有用信息。如果你决定改变主意,你仍然可以接受我的答案。BashFAQ#50,直接回答这个问题。@Charles当然可以,谢谢你的有用链接。
++ ec 2
++ echo 2
+ var=2