JQを使用して、マルチワード値のJSON文字列を連想配列に解析します。

JQを使用して、マルチワード値のJSON文字列を連想配列に解析します。

返されたデータを解析するためにbashwithを使用しています。jqhttps://ipinfo.io/json連想配列として。ほぼ仕事をする素晴らしい例を見つけました@https://gist.github.com/awesome/b3f65084c70264e87be3e72ee8abd0e5

コードはほとんどのデータを解析できますが、値に複数の単語の文字列が含まれていると失敗します。問題は、引用符を正しい場所に置くことと関係があると思いますが、どこにいるのかわかりません。私は文書を見てjq一般的なアイデアを得ましたが、詳細は私をパニックにしました。jqパイプ、テンプレート、および折りたたみの間の相互作用を理解するのに少し困難があります。(今回は初めて使ってみますが、jqかなり確実ですregex。)

私のコードバージョンは次のとおりです

locationResult=$(curl -s 'https://ipinfo.io/json')
arrayAsString=$(echo "$locationResult" | jq --raw-output '. | to_entries | map("[\(.key)]=\(.value)") | reduce .[] as $item ("associativeArray=("; . + $item + " ") + ")"')
declare -A "$arrayAsString"
echo ${associativeArray[org]}

私の場所では、org複数の単語の会社名が返され、declare -A "$arrayAsString"警告/エラーが生成され、echo ${associativeArray[org]}フィールドの最初の単語のみが生成されますorg

私はjqその結果に基づいて引用しようとします。json値にスペースが含まれている場合のbash配列へのjq出力の割り当て問題がありますが動作しませんでした。

どんな助けでも大変感謝します。

ベストアンサー1

いつでも次のことができます。

typeset -A ipinfo
while IFS= read -rd '' key && IFS= read -rd '' value; do
  ipinfo[$key]=$value
done < <(
  set -o pipefail
  curl -s https://ipinfo.io/json |
    jq -j '
      to_entries[] |
      [.key, .value | tostring] |
      map(gsub("\u0000"; "") + "\u0000") |
      add'
)

wait "$!" || exit # if curl or jq failed. Needs bash 4.4 or newer.

つまり、jq出力NULで区切られたキーと値を取得し(文字列に変換してNUL文字を削除します(bashはその変数にそれを保存できません))IFS= read -rd ''

これは、NUL文字とNULLキーを含む以外の任意のキーと値を受け入れます(不幸なbash連想配列の制限による)。ある日、NULLキーを持つ要素が追加されるとスクリプトが中断されるため、ipinfo.ioNULLキーを持つメンバーを明示的に除外する必要があります。また、bash(ksh93とは反対)は複雑/再帰的なデータ構造をサポートしていないため、値を文字列に変換しています。

zsh代わりに使用してくださいbash

typeset -A ipinfo
ipinfo=(
  ${(0)"$(
    set -o pipefail
    curl -s https://ipinfo.io/json |
      jq -j '
        to_entries |
          map([.key, .value | tostring]) |
          flatten |
          map(gsub("\u0000"; "")) |
          join("\u0000")'
  )"}
) || exit

typeset -p ipinfo

zshNULLキーは実際にサポートされており、キーと値のリストから連想配列全体を安全に割り当てる正しい方法があります。変数にNULを格納することはサポートされていますが、ここではNULを区切り文字として使用するため、値からNULを削除する必要があります。

Ksh93(シェルbashの多いAPIをコピー)は複雑なデータ構造をサポートし、ksh93v-betaバージョンはjson解析の実験的サポートも提供しますが、まだバグがあります。 jsonサポートはそれに基づいてksh2020から削除され(現在は使用されなくなりました)、ksh93u +に基づいてまだ維持されているksh93バージョンでもサポートされていないため、手動で解析を実装する必要があります。 ksh93 は変数に NUL を格納することもサポートしていません。ただし、ここで活用できる Base64 エンコーディング間変換のためのヘルパーがあります。


お客様のアプローチには、任意のコマンド実行の脆弱性が発生します。シェルパーサーがインターネット上のランダムデータに公開されることを望まない。 (コードで入力するのに適した形式で値をエンコードするように設計されています)jqを使用しても、データが予想されるタイプではない場合は問題を見落としやすいです。または/のようなものは非常に大きなアラームベルを鳴らさなければなりません。@shsheval "$untrusteddata"typesetdeclare ... "$untrusteddata"

ここでは、シェルの代わりに適切なプログラミング言語、特にbash

おすすめ記事