【问题标题】:quotes in bash argument fail with curlbash 参数中的引号因 curl 而失败
【发布时间】:2014-01-08 07:56:32
【问题描述】:

我想在 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

我明白了

  • /tmp/debug

curl --data "query=a test" http://google.com

  • /tmp/错误

curl: (6) 无法解析主机'test'' % 总计 % 接收 % Xferd 平均速度 时间 时间 时间 当前 下载上传总花费剩余速度 100 967 100 959 100 8 1060 8 0:00:01 --:--:-- 0:00:01 1572

  • /tmp/log

&lt;!DOCTYPE html&gt;...

/tmp/debug 是完美的,这正是我想要执行的,如果我复制并粘贴它就可以了。然而,错误表明“a”和“test”被拆分为 2,并且 curl 尝试将“test”作为 url。这是我不明白的

我尝试了很多不同的东西:$、$@、"$"、"*@",各种放置单引号和双引号的方法,所以经过数小时的努力,我呼吁你的帮助 !!!非常感谢

【问题讨论】:

  • 我看不出你是如何在调试中得到http://google.com
  • 由于您的示例中从未出现“google.com”,因此调试/日志输出与您显示的输入不对应。不可能知道输入的其余部分是否对应,但我对此表示怀疑,因为该示例应该以不同的方式失败。输出看起来像是来自CallAndLog curl --data '"'query=$val'"' http://google.com
  • @glennjackman 我不认为这是重复的,因为 $@ 或 $* 和引号有些可疑。 url 编码可能是一种绕过那里的方法,但我不知道它为什么会失败

标签: bash curl double-quotes


【解决方案1】:

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

调用应该很简单

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

运行之后,我们可以查看输出日志文件:

$ 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, ...

【讨论】:

  • 如果你使用 CallAndLog 'curl ..."query=$val"',$val 不会被它的值替换,因为它是单引号
  • 我还没有测试你的日志语句但是我可以告诉你我没有正确执行(见/tmp/error)
  • @Thomas 它将被evaluation 上的值替换
  • @Thomas 不,我的意思是您在 CallAndLog 中的执行行是正确的,但是您对 CallAndLog 的调用是错误的,因为您试图取悦不正确的日志语句而不是正确的执行行。答案显示了如何正确调用它。
  • 我试过了,但它没有被替换,它保持为 $val
【解决方案2】:

如您所料,问题出在res=$("$@" 2&gt; /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 返回的错误结果完全是另一个问题。

【讨论】:

  • 我不相信这个分析是正确的。 "$@" 将在参数中保留单词分隔。此外,OP 确实 想要将实际的双引号传递给 curl,afaik。
  • 是的,但是 "$@" 只保留分词,直到它被发送到$(),在这个例子中它会丢失它们。
  • 不是这样。 (set -- bash -c echo\ \"\$1\" _ "a b" c; res=$("$@"); echo "$res")
  • 从 OP 中可以清楚地看出它正在丢失 "a test" 周围的内部引号
  • “测试”周围有哪些内引号? val="a test" 不会在 $val 中添加任何引号。 (而且 curl 也不期望它们。正确的调用是 --data query=a%20test)。你当然不想要--data \"query=a%20test\"。 TIAS。
猜你喜欢
  • 1970-01-01
  • 2022-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-18
  • 1970-01-01
  • 2021-09-22
  • 2014-12-31
相关资源
最近更新 更多