파이프 구분 키 및 bash 값에서 jq를 사용하여 JSON 생성
bash 문자열에서 json 개체를 생성하려고 합니다.문자열은 다음과 같습니다.
CONTAINER|CPU%|MEMUSAGE/LIMIT|MEM%|NETI/O|BLOCKI/O|PIDS
nginx_container|0.02%|25.09MiB/15.26GiB|0.16%|0B/0B|22.09MB/4.096kB|0
이 출력은 docker stats 명령어의 출력이며 최종 목표는 사용자 지정 메트릭을 aws cloudwatch에 게시하는 것입니다.이 문자열을 json으로 포맷하고 싶습니다.
{
"CONTAINER":"nginx_container",
"CPU%":"0.02%",
....
}
이전에 jq 명령어를 사용한 적이 있는데, 이 경우 잘 될 것 같지만 아직 좋은 해결책이 나오지 않았습니다.변수 이름 하드코딩 및 sed 또는 awk를 사용한 색인화 이외.그런 다음 처음부터 json을 만듭니다.어떤 제안이라도 해주시면 감사하겠습니다.감사해요.
전제 조건
다음 모든 경우 콘텐츠는 다음과 같은 이름의 셸 변수에 있다고 가정합니다.s
:
s='CONTAINER|CPU%|MEMUSAGE/LIMIT|MEM%|NETI/O|BLOCKI/O|PIDS
nginx_container|0.02%|25.09MiB/15.26GiB|0.16%|0B/0B|22.09MB/4.096kB|0'
What(현대 jq)
# thanks to @JeffMercado and @chepner for refinements, see comments
jq -Rn '
( input | split("|") ) as $keys |
( inputs | split("|") ) as $vals |
[[$keys, $vals] | transpose[] | {key:.[0],value:.[1]}] | from_entries
' <<<"$s"
방법(현대 jq)
이것은 매우 새로운 것을 필요로 합니다(약 1.5). jq
촘촘한 코드 덩어리입니다.분석 방법:
- 사용.
-n
막다jq
입력 스트림 전체를 읽을 수 있도록 남겨두고 stdin을 스스로 읽습니다.input
그리고.inputs
-- 전자는 한 줄을 읽고 후자는 나머지 모든 줄을 읽습니다.(-R
raw 입력의 경우 JSON 오브젝트가 아닌 텍스트 행이 읽힙니다). - 와 함께
[$keys, $vals] | transpose[]
, 생성 중입니다.[key, value]
쌍(Python 용어로 두 목록의 압축을 푼다). - 와 함께
{key:.[0],value:.[1]}
, 각각을 만들고 있습니다.[key, value]
그 형식의 물체로 짝을 짓다.{"key": key, "value": value}
- 와 함께
from_entries
이러한 쌍을 이러한 키와 값을 포함하는 개체로 결합합니다.
What(셸 지원)
이것은 상당히 오래된 시스템에서 작동합니다.jq
위의 방법보다 높고, 네이티브가 다음과 같은 시나리오에 쉽게 채택되는 접근법이다.jq
솔루션 문제 해결이 더 어려워질 수 있습니다.
{
IFS='|' read -r -a keys # read first line into an array of strings
## read each subsequent line into an array named "values"
while IFS='|' read -r -a values; do
# setup: positional arguments to pass in literal variables, query with code
jq_args=( )
jq_query='.'
# copy values into the arguments, reference them from the generated code
for idx in "${!values[@]}"; do
[[ ${keys[$idx]} ]] || continue # skip values with no corresponding key
jq_args+=( --arg "key$idx" "${keys[$idx]}" )
jq_args+=( --arg "value$idx" "${values[$idx]}" )
jq_query+=" | .[\$key${idx}]=\$value${idx}"
done
# run the generated command
jq "${jq_args[@]}" "$jq_query" <<<'{}'
done
} <<<"$s"
방법(쉘 지원)
호출된jq
위의 명령어는 다음과 같습니다.
jq --arg key0 'CONTAINER' \
--arg value0 'nginx_container' \
--arg key1 'CPU%' \
--arg value1 '0.0.2%' \
--arg key2 'MEMUSAGE/LIMIT' \
--arg value2 '25.09MiB/15.26GiB' \
'. | .[$key0]=$value0 | .[$key1]=$value1 | .[$key2]=$value2' \
<<<'{}'
...각 키와 값을 대역 외(JSON으로 구문 분석되지 않고 리터럴 문자열로 처리됨)로 전달한 다음 개별적으로 참조합니다.
결과
위 중 하나가 방출됩니다.
{
"CONTAINER": "nginx_container",
"CPU%": "0.02%",
"MEMUSAGE/LIMIT": "25.09MiB/15.26GiB",
"MEM%": "0.16%",
"NETI/O": "0B/0B",
"BLOCKI/O": "22.09MB/4.096kB",
"PIDS": "0"
}
왜죠
한마디로 출력으로 유효한 JSON을 생성할 수 있기 때문입니다.
보다 순진한 접근방식을 깨뜨릴 수 있는 예로서 다음 사항을 고려해 주십시오.
s='key ending in a backslash\
value "with quotes"'
물론 예상치 못한 시나리오지만jq
대처법을 알고 있습니다.
{
"key ending in a backslash\\": "value \"with quotes\""
}
...JSON 문자열을 이해하지 못한 구현에서는 다음과 같은 결과가 쉽게 발생할 수 있습니다.
{
"key ending in a backslash\": "value "with quotes""
}
오래된 포스트인 건 알지만 당신이 찾는 도구는jo
: https://github.com/jpmens/jo
간단한 예를 다음에 나타냅니다.
$ jo my_variable="simple"
{"my_variable":"simple"}
조금 더 복잡함
$ jo -p name=jo n=17 parser=false
{
"name": "jo",
"n": 17,
"parser": false
}
어레이 추가
$ jo -p name=jo n=17 parser=false my_array=$(jo -a {1..5})
{
"name": "jo",
"n": 17,
"parser": false,
"my_array": [
1,
2,
3,
4,
5
]
}
Jo와 함께 꽤 복잡한 것들을 만들었는데, 좋은 점은 유효하지 않은 json을 만들 가능성에 대해 걱정하면서 솔루션을 굴리는 것에 대해 걱정할 필요가 없다는 것입니다.
도킹업자에게 먼저 JSON 데이터를 제공하도록 요청할 수 있습니다.
docker stats --format "{{json .}}"
상세한 것에 대하여는, https://docs.docker.com/config/formatting/ 를 참조해 주세요.
JSONSTR=""
declare -a JSONNAMES=()
declare -A JSONARRAY=()
LOOPNUM=0
cat ~/newfile | while IFS=: read CONTAINER CPU MEMUSE MEMPC NETIO BLKIO PIDS; do
if [[ "$LOOPNUM" = 0 ]]; then
JSONNAMES=("$CONTAINER" "$CPU" "$MEMUSE" "$MEMPC" "$NETIO" "$BLKIO" "$PIDS")
LOOPNUM=$(( LOOPNUM+1 ))
else
echo "{ \"${JSONNAMES[0]}\": \"${CONTAINER}\", \"${JSONNAMES[1]}\": \"${CPU}\", \"${JSONNAMES[2]}\": \"${MEMUSE}\", \"${JSONNAMES[3]}\": \"${MEMPC}\", \"${JSONNAMES[4]}\": \"${NETIO}\", \"${JSONNAMES[5]}\": \"${BLKIO}\", \"${JSONNAMES[6]}\": \"${PIDS}\" }"
fi
done
반품:
{ "CONTAINER": "nginx_container", "CPU%": "0.02%", "MEMUSAGE/LIMIT": "25.09MiB/15.26GiB", "MEM%": "0.16%", "NETI/O": "0B/0B", "BLOCKI/O": "22.09MB/4.096kB", "PIDS": "0" }
여기에서는, 다음의 솔루션을 사용하고 있습니다.-R
★★★★★★★★★★★★★★★★★」-s
옵션과 함께:
split("\n") # [ "CONTAINER...", "nginx_container|0.02%...", ...]
| (.[0] | split("|")) as $keys # [ "CONTAINER", "CPU%", "MEMUSAGE/LIMIT", ... ]
| (.[1:][] | split("|")) # [ "nginx_container", "0.02%", ... ] [ ... ] ...
| select(length > 0) # (remove empty [] caused by trailing newline)
| [$keys, .] # [ ["CONTAINER", ...], ["nginx_container", ...] ] ...
| [ transpose[] | {(.[0]):.[1]} ] # [ {"CONTAINER": "nginx_container"}, ... ] ...
| add # {"CONTAINER": "nginx_container", "CPU%": "0.02%" ...
json_template='{"CONTAINER":"%s","CPU%":"%s","MEMUSAGE/LIMIT":"%s", "MEM%":"%s","NETI/O":"%s","BLOCKI/O":"%s","PIDS":"%s"}' json_string=$(printf "$json_template" "nginx_container" "0.02%" "25.09MiB/15.26GiB" "0.16%" "0B/0B" "22.09MB/4.096kB" "0") echo "$json_string"
jq를 사용하지 않지만 값에서 arg와 환경을 사용할 수 있습니다.
CONTAINER=nginx_container json_template='{"CONTAINER":"%s","CPU%":"%s","MEMUSAGE/LIMIT":"%s", "MEM%":"%s","NETI/O":"%s","BLOCKI/O":"%s","PIDS":"%s"}' json_string=$(printf "$json_template" "$CONTAINER" "$1" "25.09MiB/15.26GiB" "0.16%" "0B/0B" "22.09MB/4.096kB" "0") echo "$json_string"
표 형식의 데이터로 시작하는 경우 sqawk와 같이 표 형식의 데이터를 기본적으로 사용하여 json으로 만든 다음 jq로 작업하는 것이 더 합리적이라고 생각합니다.
echo 'CONTAINER|CPU%|MEMUSAGE/LIMIT|MEM%|NETI/O|BLOCKI/O|PIDS
nginx_container|0.02%|25.09MiB/15.26GiB|0.16%|0B/0B|22.09MB/4.096kB|0' \
| sqawk -FS '[|]' -RS '\n' -output json 'select * from a' header=1 \
| jq '.[] | with_entries(select(.key|test("^a.*")|not))'
{
"CONTAINER": "nginx_container",
"CPU%": "0.02%",
"MEMUSAGE/LIMIT": "25.09MiB/15.26GiB",
"MEM%": "0.16%",
"NETI/O": "0B/0B",
"BLOCKI/O": "22.09MB/4.096kB",
"PIDS": "0"
}
jq
,sqawk
을 사용법을 사용하다
[
{
"anr": "1",
"anf": "7",
"a0": "nginx_container|0.02%|25.09MiB/15.26GiB|0.16%|0B/0B|22.09MB/4.096kB|0",
"CONTAINER": "nginx_container",
"CPU%": "0.02%",
"MEMUSAGE/LIMIT": "25.09MiB/15.26GiB",
"MEM%": "0.16%",
"NETI/O": "0B/0B",
"BLOCKI/O": "22.09MB/4.096kB",
"PIDS": "0",
"a8": "",
"a9": "",
"a10": ""
}
]
언급URL : https://stackoverflow.com/questions/38860529/create-json-using-jq-from-pipe-separated-keys-and-values-in-bash
'sourcetip' 카테고리의 다른 글
HTML 양식을 제출하지 않도록 합니다. (0) | 2023.03.09 |
---|---|
에서 .에서 .에서 . (0) | 2023.03.09 |
Jest: SVG 요구 원인 "SyntaxError:예기치 않은 토큰 <" (0) | 2023.03.09 |
webpack-cli에서 오류 발생: 웹 팩 구성에서 "TypeError: merge is not function" (0) | 2023.03.09 |
AngularJS에서는 한 페이지에 있는 모든 스코프를 어떻게 찾을 수 있습니까? (0) | 2023.03.09 |