因此,我需要一种方法来从 Windows 机器向 discord 发送一些 webhook,在 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"
我收到此错误:
{"code": 50006, "message": "Cannot send an empty message"}
该字符串中什么内容是 Windows 不喜欢的?
我弄乱了空格和其他东西,但只破坏了更多。
答案1
脚本中的问题实际上可以通过 Ask Ubuntu 语法突出显示非常清楚地显示出来 - 正如您在答案中所看到的,"x"
帖子中的 被涂成黑色,因为它位于双引号字符串之外,而该字符串是 参数的值-c
。bash
这个问题在您的整个代码中重复出现。
字符串在 shell 中的工作方式是,双引号是一种让多个单词(即包含空格的字符序列)在 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"
我们可以看到,您将大量代码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"
]
然后 shell 将解析字符串列表并执行 bash:
execve("bash", "-c", "curl -H Content-Type:application/json -X POST -d '{x: x, content: hello}' https://discordapp.com/some/path");
如您所见,JSON POST 负载中不再有双引号:它们被 shell 删除,以尝试理解哪些字符串构成了第二个参数。这会导致负载无效,服务器认为您没有提供输入。
顺便说一句:根据我的经验 - 你刚才所展示的是对 shell 转义如何工作的首要误解,所以不要为此感到难过 - 每个人都在这样做;-)
如果你想加双引号,你想做什么里面双引号字符串的另一种方法是“转义”它们 - 使 shell 不将它们视为特殊字符,而只是字符串文本的一部分。有两种主要方法可以做到这一点:
- 利用 shell 中的字符串实际上不需要引用的事实,字符串可以是没有空格的单词串在一起,也可以是没有空格的多个带引号的字符串串在一起。所以它看起来像这样:
"curl -H "'"'"Content-Type:application/json"'"'" ..."
。您可以看到,我们理解双引号实际上终止了从开头开始的字符串,而不是仅仅放置双引号,而实际上它不是输入的一部分,并且在 shell 看到输入结束(由于空格)之前,我们立即开始一个新字符串,这个字符串由单引号分隔 - 仅包含双引号字符,依此类推 - 这实际上类似于echo
第一个示例中的最后一个命令。 - 使用反斜杠使内部双引号字符不被视为字符串分隔符 - 将它们从解析中转义:
"curl -H \"Content-Type:application/json\" -X...
我个人比较喜欢第一种方法。