bash参数中的引号使用curl失败

bash参数中的引号使用curl失败,bash,curl,double-quotes,Bash,Curl,Double Quotes,在bash脚本中调用函数时,我希望记录各种事情,因此我尝试在一个特殊的地方完成这项工作 function CallAndLog { echo "$@" > /tmp/debug res=$("$@" 2> /tmp/error) if [ $? -gt 0 ] then echo "error : $(</tmp/error)" >> /tmp/log fi echo "$res" >> /tmp/log } val="

在bash脚本中调用函数时,我希望记录各种事情,因此我尝试在一个特殊的地方完成这项工作

function CallAndLog {
  echo "$@" > /tmp/debug
  res=$("$@" 2> /tmp/error)
  if [ $? -gt 0 ]
  then
    echo "error : $(</tmp/error)" >> /tmp/log
  fi
  echo "$res" >> /tmp/log
}

val="a test"
CallAndLog curl --data '"'"query=$val"'"' http://google.com
函数CallAndLog{
echo“$@”>/tmp/debug
res=$(“$@”2>/tmp/error)
如果[$?-gt 0]
然后

echo“error:$(正如您所猜测的,问题在于
res=$(“$@”2>/tmp/error)
。执行示例curl语句时,引号丢失,因此实际传递的是:

curl --data query=a test http://google.com
那么,我们如何解决这个问题呢?嗯,我认为最简单的方法是修改您对声明的调用方式:

val="a test"
CallAndLog curl --data query=\"${val}\"
通过转义引号,我们现在应该以正确的语法发送:

curl --data query="a test" http://google.com
此代码在本地工作

~/tmp › cat /tmp/debug 
curl --data query="a test" http://google.com

~/tmp › cat /tmp/log 
<!DOCTYPE html> <html lang=en>   <meta charset=utf-8>   <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">   <title>Error 405 (Method Not Allowed)!!1</title>   <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}} </style>   <a href=//www.google.com/><img src=//www.google.com/images/errors/logo_sm.gif alt=Google></a>   <p><b>405.</b> <ins>That’s an error.</ins>   <p>The request method <code>POST</code> is inappropriate for the URL <code>/</code>.  <ins>That’s all we know.</ins>

现在,从Google返回的错误结果是另一个问题。

您的执行正确,但日志记录不正确。这就是为什么在命令失败时日志显示良好的原因

调用应该是简单的

CallAndLog curl --data "query=$val"
要记录语句,请使用

printf "%q " "$@" >> /tmp/debug
您的引用将被重新格式化,但在语义上是相同的(即,您可以复制粘贴语句以相同的方式运行相同的命令)。这是因为引用是控制各种形式的拆分和扩展的shell语法,并且只有效果(而非语法)被带入函数中


以下是一个例子:

function CallAndLog {
  printf "%q " "$@" > /tmp/debug
  echo >> /tmp/debug # add line feed
  res=$("$@" 2> /tmp/error)
  if [ $? -gt 0 ]
  then
    echo "error : $(</tmp/error)" >> /tmp/log
  fi
  echo "$res" >> /tmp/log
}

val="a test"
CallAndLog curl --data "query=$val" http://google.com
函数CallAndLog{
printf“%q”$@>/tmp/debug
echo>>/tmp/debug#添加换行符
res=$(“$@”2>/tmp/error)
如果[$?-gt 0]
然后

echo“错误:$(可能是重复的,我不知道您是如何得到
http://google.com
在调试中自“”从未出现在您的示例中,调试/日志输出无法与您显示的输入相对应。不可能知道其余输入是否相对应,但我对此表示怀疑,因为示例应以不同的方式失败。输出看起来像来自
CallAndLog curl--data''query=$val''' http://google.com
@glennjackman我不认为它是重复的,因为$@或$*和引号有些可疑。url编码可能是一种解决方法,但我不知道它为什么会失败,我不相信这个分析是正确的。
“$@”
将保留参数中的单词分隔。此外,OP不希望将实际的双引号传递给curl,afaik.True,但“$@”仅在将其发送到
$()
时才保留单词分隔,在本例中,这是它丢失它们的时候。并非如此。
(set--bash-c echo\\\\$1\\\\\\\\\$a b”c;res=$(“$@”);echo“$res”)
从OP中可以清楚地看到,它正在丢失
“a test”的内部引号
什么是“a test”的内部引号?
val=“a test”
没有将任何引号放入
$val
中(curl也不期望它们。正确的调用是
--data query a%20test
)。您当然不希望使用
--data \“query=a%20test\”
.TIAS。如果调用ANDLOG“curl…”query=$val“,$val将不会被其值替换,因为它是单引号。我还没有测试您的日志语句,但我可以告诉您我执行得不正确(请参阅/tmp/error)@托马斯:在
eval
uation@Thomas不,我的意思是CallAndLog中的执行行是正确的,但是调用CallAndLog是错误的,因为您试图取悦错误的日志语句,而不是正确的执行行。答案显示了如何正确调用它。我已经尝试过了,但确实如此esn不会被替换,它保持为$val
$ cat /tmp/debug
curl --data query=a\ test http://google.com 

$ cat /tmp/error
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   971  100   959  100    12   6101     76 --:--:-- --:--:-- --:--:-- 43590

$ cat /tmp/log
<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, ...