2016-12-14 2 views
4

lsblk의 출력을 구문 분석해야합니다. 스크립트에서이 작업을 수행하고 있으므로 출력을 표준화 된 형식으로해야합니다. 따라서 JSON 형식을 출력으로 선택했습니다. 다음은 몇 가지 샘플 출력 명령입니다 :jq로 JSON 형식 구문 분석

# lsblk -o NAME,MOUNTPOINT -J 
{ 
    "blockdevices": [ 
     {"name": "sda", "mountpoint": null, 
     "children": [ 
      {"name": "sda1", "mountpoint": "/sda1/mountpoint"}, 
      {"name": "sda2", "mountpoint": null, 
       "children": [ 
        {"name": "sda2_mapper", "mountpoint": "/sda2/mountpoint"} 
       ] 
      }, 
      {"name": "sda3", "mountpoint": null}, 
      {"name": "sda4", "mountpoint": null} 
     ] 
     }, 
     {"name": "sdb", "mountpoint": null, 
     "children": [ 
      {"name": "sdb1", "mountpoint": "/sdb1/mountpoint"}, 
      {"name": "sdb2", "mountpoint": null} 
     ] 
     }, 
     {"name": "sdc", "mountpoint": null} 
    ] 
} 

내가 모든 안쪽 노드의 이름을 추출 할, 즉, 아이들이없는 모든 노드의 이름입니다. 위의 샘플에 대한 원하는 출력은 다음과 같습니다 선택의

sda1 
sda2_mapper 
sda3 
sda4 
sdb1 
sdb2 
sdc 

내 도구는 내가 최근에 발견 한 jq입니다. 나는 시도했다

# jq '.blockdevices[].children[]?.name?' 

그러나 이것은 이름의 첫 번째 수준 만 필터링합니다. 나는 또한 시도했다

# jq 'recurse(.name?)' 

그러나 이것은 전체 파일을 반환합니다.

중첩 된 노드가 있더라도 자식이없는 노드 만 반환 할 수있는 방법이 있습니까?

추신 : 나는 bash 또는 awk에 요구 사항을 구현할 수 있습니다. 그러나 나는 jq과 같은 도구를 사용하는 솔루션을 선호합니다. 구체적인 목적은 json 파일을 구문 분석하는 것입니다.

답변

1

나는이 그것을 할 수있는 가장 간단한 방법이라고 생각하지 않지만, 그것을 작동하는 것 같다 : 그것은 재귀 적으로 객체가 아닌 첫 아무것도 필터링의 JSON에있는 각 값을 출력

$ jq -r '.blockdevices[] | .. | objects | select(has("children")|not)| .name' tmp.json 
sda1 
sda2_mapper 
sda3 
sda4 
sdb1 
sdb2 
sdc 

을 , children 키가있는 모든 개체. 마지막으로 각 나머지 오브젝트에서 name 값을 선택할 수 있습니다. 당신의 JSON 입력으로

+0

신속한 후속 질문이 있습니다. 배열에서 이름을 캡쳐하고 후속 호출로 마운트 포인트를 얻으면 마운트 포인트는 해당 이름과 동일한 인덱스를 갖게됩니다. 맞습니까? '--sort-keys'와 같은 옵션을 추가하지 않으면 명령은 원래 출력의 순서를 변경하지 않습니다. – nautical

+0

수정하십시오. '.name' 필터 앞에있는 필터는'name'과'mountpoint' 키를 모두 포함하는 사전을 생성합니다. – chepner

0

, 다음 명령을

"sda" 
"sda1" 
"/sda1/mountpoint" 

문자열에서 인용 부호를 제거하기 위해 -r (원시 출력)를 사용

jq '.. | scalars' 

은 시작하는 "잎"을 방출 .