jq를 사용하여 여러 필드 값을 찾고 바꾸는 방법은 무엇입니까?

jq를 사용하여 여러 필드 값을 찾고 바꾸는 방법은 무엇입니까?

다음 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"'

이는 동일한 할당을 수행합니다.

  1. 최상위 개체의 "이름" 필드입니다.
  2. "이름" 필드모든연락처 배열의 객체
  3. "그룹" 배열에 있는 각 개체의 "이름" 필드입니다.

한 번에 완료됩니다. 이는 파일에 다음이 있는 경우 특히 유용합니다.다른이름 필드가 관련 없는 위치에 있으며 변경하고 싶지 않습니다. 지정된 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

신용 거래:https://github.com/stedolan/jq/issues/963

답변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 $ 

관련 정보