텍스트와 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 파일의 루트 수준에 있는 개체 목록에 일대일로 매핑되는 줄바꿈으로 구분된 문자열 목록이 포함된 파일이 있습니다.
  • 문자열 목록의 행과 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각 개체를 한 줄에 인쇄 하도록 지시하여 paste전체 JSON 개체가 각 줄 뒤에 인쇄되도록 합니다 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

답변2

나도 fra-san과 같은 가정을 하고 있어그들의 대답에, 즉 다음과 유사한 구조를 가진 잘 구성된 JSON 문서가 있습니다.

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

...JSON 입력의 객체와 동일한 줄 수의 텍스트 파일이 있습니다.

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

더 나은 단어를 원할 경우 텍스트 파일의 경로 이름을 이름이 지정된 새 키 아래의 해당 JSON 개체에 삽입하여 pathname첫 번째 경로 이름이 pathname첫 번째 개체의 키 값이 되도록 할 수 있습니다.

jq -Rn --slurpfile j input.json '$j[] | .pathname = input' input.txt

위 명령은 먼저 기존 JSON 문서를 배열 input.json로 읽어옵니다 . 그런 다음 해당 배열의 요소를 반복합니다. 즉, JSON 파일의 개체를 반복하고 함수의 반환 값으로 값이 제공되는 각 요소에 대한 키를 만듭니다 .jq$jpathnameinput

input함수는 다음 입력 데이터를 반환합니다. 이 경우 JSON 입력 대신 "원시 입력"을 제공하고 처리가 시작되면 전체 파일을 자동으로 읽는 것을 방지하여 -R및 가 모두 유효한지 확인합니다. 이는 "다음 입력"이 텍스트 파일의 다음 줄임을 의미합니다.-ninput.txtinput.txt

위의 효과는 JSON 파일의 각 개체에 대한 input.txt새 키 값으로 행을 추가하는 것입니다.pathnameinput.json

출력은 다음과 같습니다.

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

그런 다음 위의 내용을 명령에 대한 입력으로 사용하여 TagSet포함 내용이 있는 해당 개체의 경로 이름을 추출할 수 있습니다.{foo:"bar"}data.json

jq -r 'select(any(.TagSet[]; . == {foo:"bar"})).pathname' data.json

그러면 데이터를 읽고 TagSet배열 요소가 있는 개체를 선택합니다 {foo:"bar"}. 이러한 객체에서 pathname키 값을 추출합니다.

관련 정보