二重引用符をエスケープせずに正しい JSON 形式を取得することは可能ですか?

二重引用符をエスケープせずに正しい JSON 形式を取得することは可能ですか?

httpie を使用して json データを送信したいです。

二重引用符を使用し、キーを囲む二重引用符をエスケープすると、機能します。

json="[ \
    { \
        \"count\": 3 \
    } \
]"

echo $json

[ { "count": 3 } ]

でも逃げたくない。以下はコピー&ペーストの方が簡単だけど、うまくいかない。

json='[ \
    { \
        "count": 3 \
    } \
]'

echo $json

[ \ { \ "count": 3 \ } \ ]

では、json キーを囲む二重引用符をエスケープせずに、どこかからコピーして貼り付けやすくすることは可能でしょうか?

答え1

var="foo\
bar"

シーケンスは\<newline>二重引用符内では特殊ですが、一重引用符内では特殊ではありません。削除されたなので が$var含まれますfoobar

次のことをするとき:

echo $json

split+glob 演算子 (展開を引用符で囲むのを忘れた場合に呼び出される暗黙の演算子) を使用しています。つまり、 の内容は$json内の文字で分割され$IFS、各単語はファイル名生成 (別名 globbing) の対象となります。

のデフォルト値には、$IFSスペース、タブ、改行が含まれます (また、スペース、タブ、改行は、分割に関して特別な処理が行われ、それらのシーケンスは 1 つとしてカウントされ、先頭と末尾のものは無視されます)。たとえば、次のようになります。

var='  foo  *
bar'

echo $var

$varはまず に分割されfoo*barスプリット部分)*に展開され、現在のディレクトリ(グロブ一部)。

コンテンツをそのまま表示したい場合 (ただし、多くのecho実装ではコンテンツが壊れる可能性があることに注意してください)、次のように記述します。

$ echo "$json"
[     {         "count": 3     } ]

さて、スペースを圧縮することが目的であれば、split+glob 演算子をうまく活用できるかもしれません。

json='
  [
    {
      "count": 3
    }
  ]'

unset -v IFS # make sure we get a default splitting behaviour.
             # an unset -v IFS is equivalent to IFS=$' \t\n'
set -o noglob # disable the glob part

echo $json # use the split+glob operator

echo引数はスペースで区切られて出力されるため、スペース、タブ、または改行文字のシーケンスはすべて、実質的に 1 つのスペース文字に置き換えられます (先頭と末尾のスペース文字は削除され、echo最後に 1 つの改行文字が追加されます)。つまり、次のようになります。

[ { "count": 3 } ]

いずれにしても、空白が引用符で囲まれているかどうかは区別されないため、JSON データの意味が変わる可能性があります (たとえば、"foo bar"に変換されます)。"foo bar"

シーケンスを使用して\<newline>改行文字をエスケープ (削除) し、それ以外の空白文字を保持し、二重引用符文字をエスケープする必要がない場合は、ヒアドキュメントを使用できます。

json=$(cat <<EOF
  [\
    {\
      "count": 3\
    }\
  ]
EOF
)
echo "$json"

つまり、次のようになります。

  [    {      "count": 3    }  ]

(改行は削除されていますが (バックスラッシュを先頭に付けないことで改行の一部を保持することもできます)、その他の空白文字はそのまま残されています)。

答え2

引用符内の行を継続するためにバックスラッシュを使用する必要はありません。2 番目の例では、バックスラッシュは実際には有害です。なぜなら、単一引用符内ではバックスラッシュがそのまま保持され、文字列が構文的に無効になるからです。バックスラッシュを削除すれば、問題なく動作します。

関連情報