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 -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をエコーし​​ますが、それを使用してコマンドで何かが中断されるという事実が私を混乱させます。

(はい、ウェブフックアドレスを壊しました)

この質問は重複してマークされています。別の問題しかし、この質問に対する答えは、単に引用符をエスケープすることです。私のスクリプトのカールコマンドラインの「ネストされた引用符」属性のため、これらの答えは失敗しました。私の質問を投稿する前に、さまざまな形式のエスケープ引用符を試しました。他の質問に対する回答で言及されているエスケープされた引用符を使用すると、問題なく引用符内の変数の単純な「エコー」を取得できますが、「別の引用符セット内の別の引用符内に」を挿入すると、カールコマンドラインが失敗します。 。

答え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}' )

$payloadこれにより、Key-Valueフィールドの値を含む小さなJSON文書が生成されます。値は正しく引用されます(二重引用符や非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

心配すべき唯一のことは、シェル変数を引用することです。この変数は二重引用符で囲む必要があります。いつものように。パイプから読み取ったデータにリテラル引用符を挿入しようとする必要はありません。

関連情報