如何在 bash 中执行带有多个嵌套单引号和双引号以及带引号的变量的命令

如何在 bash 中执行带有多个嵌套单引号和双引号以及带引号的变量的命令

这是我的简单脚本

#!/bin/sh
thefile=/home/ark/arkserver/ShooterGame/Saved/SaveIsland/1288804998.arktribe

while inotifywait "${thefile}" ; do
    a=\"`strings ${thefile} | tail -n 5 | head -n 1 | sed 's/<[^>]*>//g'`\"
echo $a

curl -H "Content-Type: application/json" -X POST -d '{\"username\": \"Island\", \"content\": $a}' https://discordapp.com/api/webhooks/5738674701/OjRQiAWHq5mX0Tn2MfBlF-mI41TWrVYVAbOfXpeZWqo8

done

这是输出

Setting up watches.
Watches established.
/home/ark/arkserver/ShooterGame/Saved/SaveIsland/1288804998.arktribe ATTRIB
"Day 600, 21:31:17: Phorce1 demolished a 'Campfire'!"
{"code": 50006, "message": "Cannot send an empty message"}Setting up watches.
Watches established.

我不知道如何正确引用curl 命令并在中间插入变量。该命令应该是这样的。在命令行中输入时这有效

curl -H "Content-Type: application/json" -X POST -d '{"username": "test", "content": "Day 600, 14:51:00: Phorce1 demolished a 'Campfire'!"}' https://discordapp.com/api/webhooks/594723628738674701/OjRQn2MfBlF-FJVl1cWwMlD6UQf0c

我尝试过许多不同形式的引用。事实上,它与正确引用的 $a 相呼应,但仍然破坏了使用它的命令中的某些内容,这让我感到困惑。

(是的,我破坏了我的网络钩子地址)

这个问题被标记为重复另一个问题,但这个问题的答案只是简单地转义引号。我的脚本中的curl 命令行的“嵌套引号”性质导致这些答案失败。在发布我自己的问题之前,我尝试了多种形式的转义引用。使用另一个问题的答案中提到的转义引号,我可以毫无问题地得到引号内变量的简单“回显”,但将“在另一组引号内的其他引号内的引号内”插入到卷曲命令行将失败。

答案1

单引号防止变量扩展。

我会这样做:

url=https://discordapp.com/api/webhooks/5738674701/OjRQiAWHq5mX0Tn2MfBlF-mI41TWrVYVAbOfXpeZWqo8
while inotifywait "$thefile" ; do
    a=$(strings "$thefile" | tail -n 5 | head -n 1 | sed 's/<[^>]*>//g')
    echo "$a"
    payload=$(printf '{"username": "Island", "content": "%s"}' "$a")
    curl -H "Content-Type: application/json" -X POST -d "$payload" "$url" 
done

您不需要转义单引号内的双引号。事实上,如果这样做,转义字符将被保留为文字字符。

始终引用您的变量,除非您确切知道如果不引用会发生什么。

(这是个人风格的问题)你不需要将变量括在引号内,除非您需要消除变量名称与周围文本的歧义:

echo "$aVariable"
echo "${aVariable}_abc"

答案2

要创建包含用户提供的数据的 JSON 文档并对其进行正确编码等,请使用类似以下内容的内容jq

payload=$( jq --arg content "$data" -n '{"username": "Island", "content": $content}' )

这将创建一个小型 JSON 文档,其中包含键值字段中$payload的值。该值将被正确引用(双引号和非 ASCII 字符等内容将被正确处理)。$datacontent

例如,如果$data是,字面意思是

"hello
world"

(包括引号和换行符),上面的命令将创建以下 JSON 文档并将其分配给 thopayload变量:

{
  "username": "Island",
  "content": "\"hello\nworld\""
}

要删除生成文档中无用的空格,请使用jq-c选项。

完整的脚本看起来像

#!/bin/sh

url='https://discordapp.com/api/webhooks/5738674701/OjRQiAWHq5mX0Tn2MfBlF-mI41TWrVYVAbOfXpeZWqo8'
file='/home/ark/arkserver/ShooterGame/Saved/SaveIsland/1288804998.arktribe'

while inotifywait "$file" ; do
    data=$( strings "$file" | tail -n 5 | head -n 1 | sed 's/<[^>]*>//g' )
    payload=$( jq --arg content "$data" -n '{"username": "Island", "content": $content}' )

    curl -H "Content-Type: application/json" \
         -X POST \
         -d "$payload" \
         "$url"
done

您唯一需要担心的是 shell 变量的引用,它应该是双引号的照常。无需尝试将文字引号插入从管道读取的数据中。

相关内容