다음 json 파일에서
{
"email": "xxx",
"pass": "yyy",
"contact": [
{
"id": 111,
"name": "AAA"
}
],
"lname": "YYY",
"name": "AAA",
"group": [
{
"name": "AAA",
"lname": "YYY",
}
],
"name" 키를 찾아 해당 값을 "XXX"로 바꿔야 합니다. 어떤 jq 명령이 이를 수행합니까?
답변1
jq의 할당 작업은 여러 위치에서 동시에 업데이트를 수행할 수 있으며 이러한 상황을 위해 설계되었습니다. 당신은 그것을 사용할 수 있습니다
jq '(.. | .name?) |= "XXXX"'
도착하다어디서나 "name"이라는 이름의 모든 필드를 찾아 각 필드의 값을 한 번에 바꿉니다."XXXX"로 결과 객체를 출력합니다.
이건 그냥 ..|.a?
나온거야재귀 하강 문서결합하다작업 업데이트.
그것은 사용한다재귀 하강 연산자..
트리에서 각 값을 찾고 각 값에서 "이름" 필드를 추출합니다.그리고.name
,일치하지 않는 값에 대한 오류를 억제합니다.?
, 그런 다음 "XXXX"를 사용하여 이 모든 위치의 개체를 한 번에 업데이트합니다.할당 연산자 업데이트|=
, 새 객체를 출력합니다.
이는 파일 구조에 관계없이 작동하며 모든 위치의 모든 이름 필드를 업데이트합니다.
또는 파일이 항상 이 구조를 갖고 있고변경하려는 특정 "이름" 필드, 이전 이름뿐만 아니라 이름을 나열하고 그룹으로 할당할 수도 있습니다.
jq '(.name, .contact[].name, .group[].name) |= "XXXX"'
이는 동일한 할당을 수행합니다.
- 최상위 개체의 "이름" 필드입니다.
- "이름" 필드모든연락처 배열의 객체
- "그룹" 배열에 있는 각 개체의 "이름" 필드입니다.
한 번에 완료됩니다. 이는 파일에 다음이 있는 경우 특히 유용합니다.다른이름 필드가 관련 없는 위치에 있으며 변경하고 싶지 않습니다. 지정된 3개 세트의 위치만 찾아서 동시에 업데이트합니다.
값이 여기와 같은 리터럴인 경우간단한 할당과=
또한 작동하고 캐릭터를 저장합니다. (..|.name?)="XXXX"
- 전체 최상위 개체를 기반으로 값을 계산하는 경우에도 이 기능이 필요합니다. 이전 이름을 기반으로 새 이름을 계산하려면 다음을 수행하십시오.필요|=
무엇을 사용해야 할지 잘 모르겠으면 일반적으로 극단적인 경우에 더 나은 동작 을 |=
보입니다.
당신이 가지고 있다면여러 교체가 필요함, 함께 연결할 수 있습니다.
jq '(..|.name?) = "XXXX" | (..|.lname?) = "1234"'
"name" 및 "lname" 필드는 모든 곳에서 업데이트되며 업데이트된 전체 개체가 한 번 출력됩니다.
효과가 있을 수 있는 다른 접근법:
무엇을 선택하는지 매우 구체적으로 지정할 수도 있습니다.
(..|objects|select(has("name"))).name |= "XXXX"`
모든 것을 찾은 다음 개체만 찾은 다음 "이름"이 있는 개체만 찾은 다음 해당 개체의 이름 필드를 찾고 이전과 동일한 업데이트를 수행합니다.
jq의 개발 버전을 실행 중인 경우(가능성 없음)
walk
기능다음 작업도 수행됩니다walk(.name?="XXXX")
. 다른 모든 버전은 최신 릴리스 버전 1.5에서 실행됩니다.다중 업데이트의 또 다른 유형은 다음과 같습니다.
jq '(..|select(has("name"))?) += {name: "XXXX", lname: "1234"}'
그것은 모든 것을 찾아낸다그리고이름을 지정한 다음 각 개체에 "name" 및 "lname"을 설정합니다.산술 업데이트 할당*=
그리고+
개체 병합 동작.
답변2
jq
기능에 따라 사용 walk
(최신 버전 필요):
jq 'walk(.name?="XXX")' file
jq
해당 기능을 지원하지 않는 경우 walk
다음과 같이 정의하세요.
jq '
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
walk(.name?="XXX")
' file
답변3
또는,jtc
다음을 기반으로 한 솔루션:
bash $ jtc -w'<name>l+0' -u'"XXX"' your.json
{
"contact": [
{
"id": 111,
"name": "XXX"
}
],
"email": "xxx",
"group": [
{
"lname": "YYY",
"name": "XXX"
}
],
"lname": "YYY",
"name": "XXX",
"pass": "yyy"
}
bash $