テキストとJsonファイルをマージする

テキストとJsonファイルをマージする

以下のテキストファイルがあります。

AWSDynamoDB/01629227303395-c3801363/_started
AWSDynamoDB/01629227303395-c3801363/data/57sxfwx54y63xo46yhna6qgf3e.json.gz

以下のJSONファイルがあります。

{
    "TagSet": [test:tag]
}
{
    "TagSet": [foo:bar]
}

出力が次のように表示されるように、これらのファイルをマージしたいと思います。

    AWSDynamoDB/01629227303395-c3801363/_started       
{
            "TagSet": [test:tag]
        }
    AWSDynamoDB/01629227303395-c3801363/data/57sxfwx54y63xo46yhna6qgf3e.json.gz    
{
            "TagSet": [foo:bar]
        }

またはこれ。

   AWSDynamoDB/01629227303395-c3801363/_started       
                    "TagSet": [test:tag]
            
        AWSDynamoDB/01629227303395-c3801363/data/57sxfwx54y63xo46yhna6qgf3e.json.gz    
                    "TagSet": [foo:bar]
        

使ってみよう

paste input.txt output.json | pr -t -e24

しかし、それは私が探している結果を提供しません。

以下は、AWS CLIを実行したときに得られる出力です。

[cloudshell-user@ip-10-1-188-228 ~]$ aws s3api list-objects --bucket tesXXXXXnkins --query 'Contents[?LastModified<=`2021-09-07T00:00:00`].{Key:Key}' --output text | xargs -n 1 aws s3api get-object-tagging   --bucket testXXXXXkins --key
{
    "TagSet": []
}
{
    "TagSet": []
}
{
    "TagSet": []
}
{
    "TagSet": []
}
{
    "TagSet": []
}
{
    "TagSet": []
}
{
    "TagSet": []
}
{
    "TagSet": []
}
{
    "TagSet": []
}

この目標をどのように達成できますか?

ベストアンサー1

次のようにいくつかの仮定をしましょう。

  • 正しい形式のJSONファイルのルートレベルにあるオブジェクトのリストに、1対1でマップされた改行で区切られた文字列のリストを含むファイルがあります。
  • 文字列リストの行とJSONオブジェクトリストのオブジェクトのペアを出力しようとしています(各ファイルに表示される順序に応じて)。
  • あなたの質問に示されているように、出力のインデントは関係ありません。

与えられた入力データ:

$ cat input.txt
AWSDynamoDB/01629227303395-c3801363/_started
AWSDynamoDB/01629227303395-c3801363/data/57sxfwx54y63xo46yhna6qgf3e.json.gz
$ cat input.json
{
  "TagSet": []
}
{
  "TagSet": [
    {
      "foo": "bar"
    }
  ]
}

使用jqそしてpaste(BashのようなANSI C引用スタイルをサポートするシェルで$'string')、次のように書くことができます。

$ jq -rc < input.json '.' | paste -d $'\n' input.txt -
AWSDynamoDB/01629227303395-c3801363/_started
{"TagSet":[]}
AWSDynamoDB/01629227303395-c3801363/data/57sxfwx54y63xo46yhna6qgf3e.json.gz
{"TagSet":[{"foo":"bar"}]}

この-cオプションは、jq各オブジェクトを1行に印刷するように指示し、pasteJSONオブジェクト全体が各行の後に印刷されるようにしますinput.txt

より多くの入力を使用すると、jq出力をきれいに印刷できます(再びBashを想定)。

$ readarray -t lines < input.txt
$ jq -r -s \
  'range($ARGS.positional | length) as $i | $ARGS.positional[$i], .[$i]' \
  --args "${lines[@]}" < input.json
AWSDynamoDB/01629227303395-c3801363/_started
{
  "TagSet": []
}
AWSDynamoDB/01629227303395-c3801363/data/57sxfwx54y63xo46yhna6qgf3e.json.gz
{
  "TagSet": [
    {
      "foo": "bar"
    }
  ]
}

fromの各行はシェル配列の要素input.txtとして読み込まれlines、次に渡された位置引数のリストに展開されますjq
この-sオプションは、各オブジェクトに対してフィルタ処理を一度実行するのではなく、オブジェクトのリストを配列にjq読み込みます。長さに応じて(input.json
n)、jqスクリプトは1以下を繰り返します。n使用範囲i索引付けと印刷のペアは、以下で提供されます。i最初の位置引数とi最初のJSONオブジェクトです。これはexp as $identifier | ...、式の各値に対して入力データ全体に対して右側のフィルタ()を実行する設定を使用して行われます(右側のフィルタで利用可能)。...exp$identifier

おすすめ記事