내 config.json 파일에는 다음 내용이 포함되어 있습니다.
[{
"host0": "11.11.11.11",
"host1": "22.22.22.22",
"host2": "33.33.33.33",
"host3": "44.44.44.44",
"host4": "55.55.55.55",
"host5": "66.66.66.66"
}]
명령줄에서 시작할 수 있는 .sh bash 스크립트를 만들고 config.json 파일을 편집하여 전체 호스트0 줄과 해당 값을 완전히 제거하려고 합니다. 그런 다음 나머지 값을 "위로 이동"해야 합니다. 즉, 호스트1을 호스트0으로, 호스트2를 호스트1로, 호스트3을 호스트2로, 호스트4를 호스트3으로 바꾸는 등의 이름을 의미하지만 해당 값은 동일하게 유지되어야 합니다. 최종 결과는 다음과 같아야 합니다.
[{
"host0": "22.22.22.22",
"host1": "33.33.33.33",
"host2": "44.44.44.44",
"host3": "55.55.55.55",
"host4": "66.66.66.66"
}]
bash 스크립트와 jq 또는 명령줄이나 cron에서 시작할 수 있는 다른 bash 스크립트를 사용하여 이를 수행하려면 어떻게 해야 합니까? .sh 스크립트에 하드코딩되어 있습니다.jq '.host0 = "22.22.22.22" config.json옵션이 아닙니다. config.json을 읽고 호스트 1의 값을 복사하여 호스트 0 등에 붙여넣는 스크립트가 필요합니다.
답변1
다음 jq
표현식은 최상위 배열의 각 요소에 변환을 적용합니다(질문의 배열에는 요소가 하나만 있습니다). 변환에는 가장 최근에 추가된 키+값의 값을 끝에 추가된 요소의 값으로 대체하여 지정된 키와 값에서 새 배열을 구축하는 작업이 포함됩니다. 그러면 첫 번째 값이 질문에서 버려야 하는 값이고 마지막 키가 질문에서 버려야 하는 키인 길이의 배열 n+1
(여기서 n
원래 배열 요소의 키와 값 수) 이 생성됩니다. 질문. (로 쓸 수도 있음 )을 사용하면 첫 번째와 마지막 요소를 버리고 키와 값 목록을 남깁니다.11.11.11.11
host5
.[1:-1]
del(first,last)
n-1
jq 'map(to_entries | reduce .[] as $a ([{}]; last.value = $a.value | . += [$a]) | .[1:-1] | from_entries)' file
다음은 jq
좀 더 읽기 쉬운 형식의 표현식입니다.
map(
to_entries |
reduce .[] as $a (
[{}];
last.value = $a.value |
. += [$a]
) |
del(first, last) |
from_entries
)
다음 JSON 문서를 file
보면
[
{
"host0": "11.11.11.11",
"host1": "22.22.22.22",
"host2": "33.33.33.33",
"host3": "44.44.44.44",
"host4": "55.55.55.55",
"host5": "66.66.66.66"
},
{
"server0": "Atlantis",
"server1": "Gotham",
"server2": "Rivendell",
"server3": "Asgard",
"server4": "Hogwarts",
"server5": "Neverland"
}
]
...이 jq
명령은 다음과 같은 결과를 생성합니다.
[
{
"host0": "22.22.22.22",
"host1": "33.33.33.33",
"host2": "44.44.44.44",
"host3": "55.55.55.55",
"host4": "66.66.66.66"
},
{
"server0": "Gotham",
"server1": "Rivendell",
"server2": "Asgard",
"server3": "Hogwarts",
"server4": "Neverland"
}
]
키 또는 값 문자열은 해석되지 않습니다.
답변2
jq
이 파일을 사용하고 편집하는 스크립트:
#!/bin/sh
set -eu
jq '[.[] | to_entries[1:] | map(.key |= sub("(?<n>\\d+)$";"\((.n|tonumber)-1)")) | from_entries]' "$1" > "$1.tmp"
mv "$1.tmp" "$1"
용법:
$ cat config.json
[{
"host0": "11.11.11.11",
"host1": "22.22.22.22",
"host2": "33.33.33.33",
"host3": "44.44.44.44",
"host4": "55.55.55.55",
"host5": "66.66.66.66"
}]
$ ./script.sh config.json
$ cat config.json
[
{
"host0": "22.22.22.22",
"host1": "33.33.33.33",
"host2": "44.44.44.44",
"host3": "55.55.55.55",
"host4": "66.66.66.66"
}
]
형식이 약간 변경되었지만 문제가 되지는 않습니다.
형식을 유지하거나 표준 Unix 도구를 사용하려는 경우 awk
not 을 사용할 수도 있지만 jq
덜 강력합니다.
awk -F\" 'BEGIN{OFS=FS} $2=="host0"{next} $2~/^host/{$2="host" substr($2,5)-1} 1' "$1" > "$1.tmp"
답변3
만약에자바스크립트허용된:
그 외에도 구문 분석을 수행하는 특수 언어가 이미 있다는 아이디어가 있습니다.JSON~처럼내장또한 ~으로 알려진
자바스크립트객체 표기법=)
#!/bin/sh
node -e '
function renameKey (obj, oldKey, newKey) {
obj[newKey] = obj[oldKey];
delete obj[oldKey];
}
var j = require("./file.json"); // mandatory ./
delete j[0]["host0"];
let count = Object.keys(j[0]).length;
for (let i = 0; i < count; i++) {
let oldv = "host"+(i+1);
let newv = "host"+i;
renameKey(j[0], oldv, newv)
}
console.log(JSON.stringify(j, null, 4))
'
또는
#!/bin/sh
node -p '
JSON.stringify(
require("./file.json")
.map(x => {
let ok;
for (const [k, v] of Object.entries(x)) {
if (ok)
x[ok] = v;
ok = k;
}
delete x[ok];
return x;
})
, null
, 4
)
'
emanuele6에 대한 크레딧은 다음에서 제공됩니다.[이메일 보호됨].
산출
[
{
"host0": "22.22.22.22",
"host1": "33.33.33.33",
"host2": "44.44.44.44",
"host3": "55.55.55.55",
"host4": "66.66.66.66"
}
]
또 다른 방법은 다음을 사용하십시오 rhino
.
$ dpkg -s rhino
Installed-Size: 55
[...]
Description: JavaScript engine written in Java
Rhino is an implementation of the JavaScript language written
entirely in Java. It is typically embedded into Java applications to
provide scripting to end users.
Original-Maintainer: Debian Java Maintainers <[email protected]>
Homepage: http://www.mozilla.org/rhino/
(해키 방식이므로 프로덕션에서는 사용하지 마세요)
rhino -e "
function renameKey (obj, oldKey, newKey) {
obj[newKey] = obj[oldKey];
delete obj[oldKey];
}
j = $(< file.json); // shell hack to read file without import fs lib
delete j[0]['host0'];
let count = Object.keys(j[0]).length;
for (let i = 0; i < count; i++) {
let oldv = 'host'+(i+1);
let newv = 'host'+i;
renameKey(j[0], oldv, newv)
}
print(JSON.stringify(j, null, 4))
"
답변4
사용행복하다(이전 Perl_6)
~$ raku -e 'my @json = lines[1..*-2]>>.split(/ <[:,]> /, :skip-empty); put qb[\[\{]; \
@json = join ",\n", ([Z] @json[0..*]>>.[0], @json[1..*]>>.[1])>>.join(":"); \
.put for @json; put qb[\}\]];' file
나는 이 답변을 작성하는 것을 주저했지만 OP에 정렬 오류가 발생한 것 같습니다. 이미 게시된 답변이 입력 순서를 유지하는 것 같아서 다행이지만 jq
, 적어도StackOverflow 게시물보장되지는 않는다고 하더군요. ~에서RFC_8259:
> An object is an unordered collection of zero or more name/value
> pairs, where a name is a string and a value is a string, number,
> boolean, null, object, or array.
위의 Raku 코드는 텍스트에 대해 리터럴 접근 방식을 취하여 첫 번째 및 마지막 대괄호 줄을 제거 lines
하면서 텍스트를 배열로 읽 [1..*-2]
습니다(JSON 포맷터가 대괄호/중괄호를 한 줄 대신 두 줄에 넣는 경우 이 색인을 조정하십시오). 각 줄은 <[:,]>
콜론과 쉼표로 구성된 사용자 정의 문자 클래스로 분할되고 :skip-empty
빈 요소는 제거됩니다. 이러한 방식으로 각 @
배열 위치에는 호스트와 IP라는 두 가지 요소가 포함됩니다.
대괄호/중괄호는 put
별도의 명령문으로 다시 사용됩니다. 배열 은 함께 "압축" @json
되어 [Z]
첫 번째 "IP" 요소를 제거합니다(따라서 @json[1..*]>>.[1]
처음부터 제거되지 않음). 항목의 요소가 부족해지면 압축이 중지됩니다. 마지막으로 콜론, 쉼표 및 줄 바꿈이 다시 삽입됩니다.1..
0..
join
입력 예:
[{
"host0": "11.11.11.11",
"host1": "22.22.22.22",
"host2": "33.33.33.33",
"host3": "44.44.44.44",
"host4": "55.55.55.55",
"host5": "66.66.66.66"
}]
예제 출력:
[{
"host0": "22.22.22.22",
"host1": "33.33.33.33",
"host2": "44.44.44.44",
"host3": "55.55.55.55",
"host4": "66.66.66.66"
}]