아래와 같은 텍스트 파일이 있습니다.
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
$j
pathname
input
이 input
함수는 다음 입력 데이터를 반환합니다. 이 경우 JSON 입력 대신 "원시 입력"을 제공하고 처리가 시작되면 전체 파일을 자동으로 읽는 것을 방지하여 -R
및 가 모두 유효한지 확인합니다. 이는 "다음 입력"이 텍스트 파일의 다음 줄임을 의미합니다.-n
input.txt
input.txt
위의 효과는 JSON 파일의 각 개체에 대한 input.txt
새 키 값으로 행을 추가하는 것입니다.pathname
input.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
키 값을 추출합니다.