【问题标题】:BASH: passing curl parameters as $1 variableBASH:将 curl 参数作为 $1 变量传递
【发布时间】:2015-03-11 17:37:08
【问题描述】:

我有一个具有以下功能的 bash 脚本:

function curl_the_URL_and_check_status(){

   status=$(curl $1 | grep "X-Cache-Status:" | cut -d " " -f 2)

   if [[ "$status" != *"MISS"* ]]; then
       echo "
   cURL returned non MISS status. Something is not correct. Exiting with status 1
   check the status by entering curl $1"
       exit 1
   fi
}

传递参数:

## My comment :: .... some more output ....
+++ grep -o -P '(?<=\/\/).*?(?=\/)'
++ host=php-mindaugasb.c9.io
+++ echo http://php-mindaugasb.c9.io/Testing/JS/displayName.js
+++ perl -pe 's|(?<=://).+?(?=/)|localhost:805|'
++ modified_URL=http://localhost:805/Testing/JS/displayName.js

## My comment ::  below is the parameter passed to the function as $1
++ cURL_string='-H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js'

我把它传递给 curl:

++ echo -H '"Host:' 'php-mindaugasb.c9.io"' -I -s http://localhost:805/Testing/JS/displayName.js

从控制台尝试哪个不起作用(引发网关超时错误)。

所以我的卷曲看起来像这样:

curl -H '"Host:' 'php-mindaugasb.c9.io"' -I -s http://localhost:805/Testing/JS/displayName.js

我需要它看起来像这样(从控制台测试时有效):

curl -H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js

我该如何做到这一点?

尝试使用 `curl $1`, curl "$1" ...

谢谢

附录

我这样调用函数:

 # another function that constructs correct CURL string
 cURL_string="\"-H Host: $host\" -I -s $modified_URL"

 # global scope - this is where the curl is called
 curl_params=$(get_prepared_string_for_cURL $1)
 curl_the_URL_and_check_status $curl_params

(更新日期:2015 年 1 月 14 日)

这是我使用数组方法得到的结果:

cURL_string=(-H \"Host: $host\" -I -s $modified_URL)

案例:

curl "${curl_params[@]}" ==> curl '-H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js'

curl:没有指定 URL!

curl ${curl_params[@]} ==> curl -H '"Host:' 'php-mindaugasb.c9.io"' -I -s http://localhost:805/Testing/JS/displayName.js

我需要

curl -H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js

get_prepared_string_for_cURL

function get_prepared_string_for_cURL(){

    # get the host from URL, to use with in curl with the --Host flag
    host=$(echo $1 | grep -o -P '(?<=\/\/).*?(?=\/)')

    # replace the host part with the "localhost:805" to request the resource
    # from the nginx virtual host (server block) dedicated for proxy cache
    modified_URL=$(echo $1 | perl -pe 's|(?<=://).+?(?=/)|localhost:805|')

    # construct cURL string
    cURL_string=(-H Host: $host -I -s $modified_URL)

    # echo "$cURL_string"

    echo "${cURL_string[@]}"
}

【问题讨论】:

  • 使用 $@ 而不是 $1
  • 感谢您的输入,但调试器仅显示: curl "@1" 和 curl @1 用于 qouted 和 unqouted 版本。另外,我现在将添加,我如何将参数传递给调用 curl 的函数...请检查,也许这样会更容易帮助
  • 什么是get_prepared_string_for_cURL
  • 一个函数 - 我在上面添加了它的实现

标签: linux bash curl


【解决方案1】:

shell 解析引号之前 替换变量引用(例如$1),所以如果$1 的值中有引号,当它们到位时为时已晚他们做任何有用的事情。与其将 curl 参数作为嵌入引号的单个参数传递,不如将其作为一系列参数传递并使用 "$@" 来扩展它:

function curl_the_URL_and_check_status(){

   status=$(curl "$@" | grep "X-Cache-Status:" | cut -d " " -f 2)
[...]

...然后用类似这样的方式调用它:

curl_the_URL_and_check_status -H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js

代替:

curl_the_URL_and_check_status '-H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js'

但看起来您也在变量中构建参数列表,这会导致完全相同的问题 - 没有好的方法可以获取普通变量并根据嵌入的引号将其拆分为参数。同样,有一个解决方案:使用一个数组,每个参数都是数组的一个元素。然后,将数组引用为"${arrayname[@]}",这样每个元素都会被视为一个单独的参数。

cURL_args=(-H "Host: php-mindaugasb.c9.io" -I -s "$modified_URL")
curl_the_URL_and_check_status "${cURL_args[@]}"

【讨论】:

  • 我不知道我是否正确理解了你的答案,但让我接受这个说法“没有很好的方法来获取一个普通变量并将其拆分为基于嵌入引号的参数” - 我是不尝试拆分传递的变量我正在尝试在函数内构造 curl 参数,然后使用 echo 将它们从该函数传递给 curl :) 请参阅我上面的更新(更新:2015 年 14 月 1 日)——告诉我如果你的答案也能解决这个问题
  • 似乎 bash 在我执行分配时添加了单个 qoutes (curl '-H Host x -I ')(这无论如何 - 我可以传递数组或变量) - 这是语句:“curl_params=$(get_prepared_string_for_cURL $1)”所以我只是通过在函数内部构建参数但在全局范围内创建一个字符串来绕过分配 - 这是一个好习惯还是应该避免?我知道这不太清楚(至少看起来如此)。
  • @MindaugasBernatavičius 如果我理解您的更新正确,问题是您在创建数组时转义了引号 - 使用 cURL_string=(-H "Host: $host" -I -s $modified_URL) 而不是 cURL_string=(-H \"Host: $host\" -I -s $modified_URL)。引号被转义后,它们被视为参数的一部分,而不是参数周围的分隔符。然后在引用数组时使用双引号(参见我的最后一个示例)。
  • 哦,您看到单引号的原因是 bash 明确显示参数的方式。它不是“真的”在那里,但是 bash 必须添加一些东西来表明在某些参数中嵌入了双引号(您不想要),而不是在它们周围(您确实想要)。解决问题后,单引号仍然存在,但它们将代替双引号(而不是除了它们之外)。
  • 最后一点:您说您不是要拆分变量,但这实际上正是您所做的。 curl 的每个参数都是一个字符串,所以curl 的参数是一个 字符串列表。但是一个普通的 shell 变量只能存储一个字符串,所以为了把它变成一个字符串列表(参数),它必须被拆分。分裂是所有混乱的来源。数组解决了这个问题,因为它包含......几个单独的字符串。不需要拆分,它们基本上已经是正确的形式了。
【解决方案2】:

你可以使用eval先解释命令字符串中的变量,然后再执行它

更新:

eval [arg ...]
          The args are read and concatenated together into a single command.  This command is then read and  exe‐
          cuted  by  the  shell,  and its exit status is returned as the value of eval.  If there are no args, or
          only null arguments, eval returns 0.

这样你就可以在运行后构建一个类似command="curl -H \"Content-Type: whatever\" $1 $2" 的命令字符串

eval ${command}

eval 将首先读取并解释所有引用、转义和变量,然后运行解释的命令。希望这可以帮助。问候。

【讨论】:

  • 谢谢,请问您能补充一些细节吗?
  • 请不要使用eval,除非您完全了解您在做什么。它会解释字符串中的everything,无论你是否希望它被解释。它因引起讨厌的错误而享有当之无愧的声誉......
  • @GordonDavisson 你有关于那些“讨厌的错误”的更多信息吗?我很想知道我在不再使用eval 时会避免什么。
  • @EmilKakkau:基本问题是它模糊了数据和可执行代码之间的界限(甚至比通常在 shell 中更远),最终可能会执行一些你认为是数据的东西。它有多危险取决于您执行它的命令的可预测性;你对它的控制越少,它就越危险(但如果它是高度可预测的,你为什么还需要eval?)。例如,假设您要获取的 URL 包含来自不受信任来源的数据——如果 URL 包含 $(rm -R *),则 eval 命令将执行 rm -R *
  • @EmilKakkau:这里有一些讨论它的链接:BashFAQ #48an SO question on the subject,以及 a made-up but extreme example
猜你喜欢
  • 2018-05-25
  • 1970-01-01
  • 1970-01-01
  • 2016-05-31
  • 2021-11-25
  • 1970-01-01
  • 2015-12-26
  • 1970-01-01
相关资源
最近更新 更多