在bash变量扩展中出现奇怪的字符

时间:2017-05-11 23:04:00

标签: bash macos shell curl command-line

尝试在contos7上执行以下操作正如我所料:

pod_in_question=$(curl -u uname:password -k very.cluster.com/api/v1/namespaces/default/pods/ | grep -i '"name": "myapp-' | cut -d '"' -f 4)

echo "$pod_in_question"

curl -u uname:password -k -X DELETE "very.cluster.com/api/v1/namespaces/default/pods/${pod_in_question}"

但是,在MacOS(10.12.1)上尝试相同的操作会产生:

  

卷曲:(3)第92栏中的[全局]坏范围

当我尝试使用-g选项 curl 最后一行时,它会替换为格式错误的名称,例如:myapp-\\x1b[m\\x1b[Kl1eti\

echo语句总是执行得很好,并显示myapp-v7454之类的东西,我后来想把它放到最后一个curl语句中。那么这些其他角色来自哪里呢?

2 个答案:

答案 0 :(得分:3)

强大的解决方案 - 基本cURL CLI调试。

在确定OP的问题与卷曲应用颜色输出有关后,对此答案进行了修订。

提出的答案清楚地解释了嵌入的特殊字符的含义,以及覆盖grep行为以不输出颜色的说明。当然,grep在管道中使用这是一个很好的做法。然而,有许多最佳实践可以帮助诊断cURL这个或类似的问题,并最终导致最强大的解决方案。

重新创建问题

  1. 假设它是JSON内容类型,我们使用echo {'"name": "myapp-7414"'}来模拟cURL的输出
  2. 我们过滤文本并使用cURL命令
  3. 中的变量设置变量
  4. 我们强制grep输出颜色,因为在输出到tty时默认情况下它并不正常。

    娱乐:

    myvar=$(echo {'"name": "myapp-7414"'} | grep --color=always -i '"name": "myapp-' | cut -d '"' -f 4)
    curl "https://www.google.com/${myvar}"
    

    输出

    curl: (3) [globbing] bad range in column 32
  5. 首先: '{}'cURL期间的特殊字符。

    • cURL中网址语法的最佳做法:

      • 如果需要变量扩展:

        • 应用-g开关以禁用由cURL
        • 完成的潜在通配
      • ,否则:

        • 使用$variable作为"引用"的一部分url字符串,而不是${variable}

    第二:除了-g之外,我们还添加了--libcurl /tmp/libcurl,以便我们了解cURL正在看到的内容。

    使用-g--libcurl进行娱乐:

    • curl -g --libcurl /tmp/libcurl  "https://www.google.com/${myvar}"

      输出

        

      <p>Your client has issued a malformed or illegal request <ins>That’s all we know.

    完美,至少现在一切都进入服务器并返回!让我们看看cURL发送到服务器的内容:

    cat /tmp/libcurl
    

    我们当然找到了这一行:(请注意粗体部分)。

    curl_easy_setopt(hnd, CURLOPT_URL, "https://www.google.com/myapp-\033[m7414");

    所以我们知道:

    1. shell 对我们的变量做了一些奇怪的事。
    2. cURL知道在我们发送-g开关后不尝试使用glob。这样 - 如果 有一个shell变量错误,我们实际上可以它是什么。如果我们不尝试使用网址范围,我们就不应该调试全局错误。
    3. 特殊字符是颜色。它们代表我们为模拟OP环境而添加的--color=always
    4. 此时此刻。由于看起来我们正在使用JSON数据,为什么不使用广泛可用的高性能JSON解析工具。这有很多好处,包括:

      • 不依赖任何可能影响字符串过滤的环境
      • 可以请求我们想要的数据(又名。&#34;名称&#34;)
      • 应用名称&#34; myapp&#34;可以改变,我们不必重新编写代码来检索它。
      • 它更清洁,并解释了我还没有考虑过的事情。

      如果我们使用jq作为示例(虽然我们正在使用{我们不需要-g切换,因为我们不需要&#39; { }&#39;为变量,因为我们已经加倍"网址):

      myvar=$(echo {'"name": "myapp-7414"'} | jq -r .name)
      curl --libcurl /tmp/libcurl "https://www.google.com/$myvar"
      

      现在我们得到:

        

      &lt; p&gt;在此服务器上找不到请求的网址/myapp-7414 这就是我们所知道的。


      很好。现在一切正常。显而易见的是,这里的测试网址www.google.com显然不会知道是myapp-7414

      所以我们已经离开了:

      • 全球范围不佳,致:
      • 格式错误的网址:
      • 在服务器上找不到网址。

      我们 也可以按其他地方的建议更改grep输出并将其覆盖为--color=never(正如我所说:如果必须使用grep--color=never是一种很好的方式,可以在管弦乐时使用它作为最佳实践。然而,考虑到由于字符串过滤已经经历过的可移植性问题,以及我们已经将结构化数据传递到可以可靠地解析的板上的事实,如果可能的话,更强大的解决方案就是这样做。

答案 1 :(得分:0)

您在最后一部分显示的替换看起来像是您的一个注入ANSI escape sequences grep 可能无法检测到非TTY输出并且正在着色。

在支持ANSI转义序列的终端上,您的特定代码可能不可见。代码^E[m^E[K设置屏幕模式并清除当前行。这就是为什么你认为echo命令证明你的数据是正确的。

您可以使用以下方法检查原始数据:

echo "$pod_in_question" | hexdump -C

你应该看到其他人物之前没有出现在你的终端中。当你把这些&#34;隐形&#34;代码到URL中, curl 尝试对它们进行编码,然后在遇到控制字符(ESC)时失败。

解决方法是将参数--color=never添加到 grep 调用中,这将禁用着色。