Windows 中的 Bash 用法:“无法发送空消息”错误

Kie*_*eps 3 windows bash windows-subsystem-for-linux 18.04

所以我需要一种方法来从 Windows 机器发送一些 webhooks 来不和谐,在 Linux 中这样做是没有问题的curl,所以我从 Windows 应用商店将 Ubuntu 18 LTS 安装到机器上并试了一下。

这是问题开始的地方,当我在 Windows 中使用相同的命令时:

bash -c "curl -H "Content-Type:application/json" -X POST -d '{"x": "x", "content": "hello"}' https://discordapp.com/api/webhooks/536660752111763477/zkW73A97-TNJVcH3xMCK0GMHEkwqKNWSfslA0WxxxxxxMYOLTRi6UMXYR_QLDCfxIJ_d"
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

{"code": 50006, "message": "Cannot send an empty message"}
Run Code Online (Sandbox Code Playgroud)

Windows 不喜欢的字符串中有什么?

我弄乱了空格和其他东西,但只会破坏更多。

Gus*_*uss 5

Ask Ubuntu 语法突出显示实际上非常清楚地显示了脚本中的问题 - 正如您在答案中看到的那样"x",您的帖子中的内容为黑色,因为它位于作为-c参数值的双引号字符串之外到bash。这个问题在您的代码中反复出现。

字符串在 shell 中的工作方式是双引号是一种让多个单词(即包含空格的字符序列)在 shell 中显示为单个单词的方法。然后外壳程序将这些单词按原样传递给程序以供运行 - 没有封闭的字符串双引号。您还可以通过将文本拼凑在一起而没有空格,从而将文本组合成同一个单词。

因此,以下命令对于 shell 都是相同的,并且将显示相同的输出:

  • echo 123
  • echo "1"23
  • echo "1"2"3"
  • echo "1"'2'"3"

在所有情况下,echo只看到文本“ 123”(最后一个我放在一些单引号中,对于许多效果来说,它的行为是相同的。

因此,考虑到这一点,让我们分析您的脚本行:

bash -c "curl -H "Content-Type:application/json" -X POST -d '{"x": "x", "content": "hello"}' https://discordapp.com/some/path"
Run Code Online (Sandbox Code Playgroud)

我们可以看到你传递了很多代码bash作为-c参数,也就是“要运行的命令”。因此bash将使用两个参数运行 - 第一个是-c,第二个是应该被视为“命令”的所有文本。第二个参数使用双引号字符串(是的,复数)来编码一些空格和其他 shell 字符,因此它们将按原样传递给“要运行的命令”参数。

让我们通过将所有“单词”转换为经典编程语言字符串数组来手动执行 shell 为理解第二个参数所做的工作:

var a = [
"-c",
"curl -H " + "Content-Type:application/json" + " -X POST -d '{" + "x" + 
  ": " + "x" + ", " + "content" + ": " + "hello" + 
  "}' https://discordapp.com/some/path"
]
Run Code Online (Sandbox Code Playgroud)

然后 shell 将解析字符串列表并执行 bash:

var a = [
"-c",
"curl -H " + "Content-Type:application/json" + " -X POST -d '{" + "x" + 
  ": " + "x" + ", " + "content" + ": " + "hello" + 
  "}' https://discordapp.com/some/path"
]
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,JSON POST 负载中不再有双引号:它们被 shell 删除,试图了解构成第二个参数的字符串。这会导致有效负载无效并且服务器认为您没有提供输入。

顺便说一句:根据我的经验 - 你刚刚展示的是对 shell 转义如何工作的第一个误解,所以不要为此感到难过 - 每个人都在这样做;-)

你想要做的,如果你想要把双引号什么里面一个双引号字符串是“逃”出来-使外壳没有看到他们为特殊字符,但作为字符串文本的只是一部分。有两种主要方法可以做到这一点:

  1. 利用 shell 中的字符串实际上不需要引用的事实,可以只是没有空格的单词组合在一起,或者多个引用的字符串组合在一起而没有空格。因此,它可能看起来像这样:"curl -H "'"'"Content-Type:application/json"'"'" ..."。你可以看到,不是仅仅放一个双引号,我们理解双引号实际上终止了从开头开始的字符串,实际上并不是输入的一部分,并且在 shell 看到输入的结尾之前(由于一个空格)我们立即开始一个新字符串,这个字符串由单引号分隔 - 只包含一个双引号字符,等等 - 这实际上类似于echo第一个示例中的最后一个命令。
  2. 使用反斜杠使内部双引号字符不被视为字符串分隔符 - 将它们从解析中转义: "curl -H \"Content-Type:application/json\" -X...

我个人更喜欢第一种方法。