Jsonの値をx回の変数として使用する

Jsonの値をx回の変数として使用する

アイテムリストのIDを含むjsonファイルがあります。

[
    {
        "list_id": 1,
        "list_key": "gnfijgndngd458wjfisdnfpon",
        "entries": 0
    },
    {
        "list_id": 2,
        "list_key": "gnfijgndndfp[mfphm,]ordjkt9roh,mkn",
        "entries": 0
    },
    {
        "list_id": 3,
        "list_key": "gnfijgnsnfc0wr8envpuh-[sijjnhmgmvisbfusf",
        "entries": 0
    }
]

各項目の最大項目数は100個です。これはlist_idを100回しか使用できないことを意味します。

bashスクリプトでこれらのIDを変数としてどのように使用できますか? 100項目以降は別のlist_idに変更する必要があります。

ベストアンサー1

list_id100未満の値を持つトップレベルの匿名配列のentries最初の要素を取得するには、次のようにします。

jq 'map(select(.entries < 100)) | first.list_id' file

(これは整数list_id値を返します。)

entries値を1ずつ増やすには

jq 'map(select(.entries < 100)) | first.entries += 1' file

list_idまたは、値を増やす特定の値がある場合は、entires各値がlist_id一意であるとします。

jq --argjson list_id "$list_id" 'map(select(.list_id == $list_id).entries += 1)' file

(これらの文書は更新された文書を返します。)

したがって、シェルスクリプトで次のようにします。

# get list_id
list_id=$( jq 'map(select(.entries < 100)) | first.list_id' file )

# check whether we got the string "null" back, which indicates
# that we found no entry ith "entries" less than 100
if [ "$list_id" = null ]; then
    echo 'No list_id with entries < 100 available' >&2
    exit 1
fi

# increment counter (in-place edit using GNU sponge)
jq --argjson list_id "$list_id" 'map(select(.list_id == $list_id).entries += 1)' file | sponge file

上記のスクリプトを110回実行した後のJSONドキュメントはfile次のとおりです(すべてのentriesカウンタが0から始まると仮定)。

[
   { "entries": 100, "list_id": 1, "list_key": "gnfijgndngd458wjfisdnfpon" },
   { "entries": 10, "list_id": 2, "list_key": "gnfijgndndfp[mfphm,]ordjkt9roh,mkn" },
   { "entries": 0, "list_id": 3, "list_key": "gnfijgnsnfc0wr8envpuh-[sijjnhmgmvisbfusf" }
]

値が0以外の場合、上記のシェルスクリプトは対応する()オプションをlist_id使用して短縮できます。jq-e--exit-status

if ! list_id=$( jq -e 'map(select(.entries < 10)) | first.list_id' file )
then
    echo 'No list_id with entries < 100 available' >&2
    exit 1
fi

# increment counter (in-place edit using GNU sponge)
jq --argjson list_id "$list_id" 'map(select(.list_id == $list_id).entries += 1)' file | sponge file

上記のコードのどれもファイルロックを実行しようとせず、複数の同時プロセスがスクリプトを実行している場合、コードには明らかな競合状態があります(list_idカウンタのインポートと更新が単一のアトミック操作ではないため)。 。

おすすめ記事