나는 사용하고있다
awk -F'[":]' '$2=="id"{printf("pri,%s,",$5)}$2=="name"{printf("%s,",$5)}$2=="objectId"{printf$4}$2=="polledName"{print$5}' | sed -e 's/, /,/g'
이것이 되었다
}, {
"id" : "1",
"name" : "host1",
"objectId" : 0001,
"polledName" : "192.168.1.1"
}, {
"id" : "2",
"name" : "host2",
"objectId" : 0002,
"polledName" : "192.168.1.2"
}, {
"id" : "3",
"name" : "host3",
"objectId" : 0003,
}, {
"id" : "4",
"name" : "host4",
"objectId" : 0004,
"polledName" : "192.168.1.3"
}, {
이것을 입력하세요
pri,1,host1,0001,192.168.1.1
pri,2,host2,0002,192.168.1.2
pri,3,host3,0003,pri,4,host4,0004,192.168.1.3
polledName에 대한 항목이 존재하지 않을 때 현재 줄로 줄 바꿈하는 대신 다음 줄로 이동하도록 이를 수정하는 방법에 대한 아이디어가 있습니다. 즉, $5가 아무것도 반환하지 않으면 개행을 추가하세요.
위의 코드는 awk 스크립트가 gawk -o-
읽기 쉽게 인쇄되어 있습니다.
awk -F'[":]' '
$2 == "id" {
printf "pri,%s,", $5
}
$2 == "name" {
printf "%s,", $5
}
$2 == "objectId" {
printf $4
}
$2 == "polledName" {
print $5
}
' | sed -e 's/, /,/g'
답변1
누구에게나하다명령줄에서 JSON 작업을 위한 적절한 도구에 액세스하면 다음을 사용하여 필드를 참조된 CSV 데이터 세트로 추출할 수 있습니다 jq
.
$ jq -r '.[] | [ "pri", .id, .name, .objectId, .polledName ] | @csv' file
"pri","1","host1",1,"192.168.1.1"
"pri","2","host2",2,"192.168.1.2"
"pri","3","host3",3,
"pri","4","host4",4,"192.168.1.3"
이는 질문에 표시된 데이터가 최상위 배열의 일부이고 올바른 형식이라고 가정합니다(질문의 세 번째 요소에 잘못된 후행 쉼표가 포함되어 있음).
[
{"id":"1","name":"host1","objectId":1,"polledName":"192.168.1.1"},
{"id":"2","name":"host2","objectId":2,"polledName":"192.168.1.2"},
{"id":"3","name":"host3","objectId":3},
{"id":"4","name":"host4","objectId":4,"polledName":"192.168.1.3"}
]
따옴표로 묶인 빈 문자열로 바꾸려면아무것도 없다누락된 .polledName
값 의 경우 .polledName
표현식을 jq
로 변경합니다 .polledName // ""
. null
키를 사용할 수 없거나 해당 값이 있는 경우 값 대신 빈 문자열을 사용합니다 null
.
탭으로 구분된 값을 얻으려면 출력 연산자 @csv
로 변경하세요 .@tsv
이를 수행하기 위해 JSON 인식 도구를 사용하면 JSON으로 인코딩된 데이터가 아닌 디코딩된 문자열을 출력에서 얻을 수 있다는 이점이 있습니다. 또한 포함된 따옴표 등은 자동으로 올바르게 처리되며 JSON 입력이 한 줄에 있는지 또는 다른 특별한 방식으로 형식이 지정되는지는 중요하지 않습니다.
답변2
꼭 사용해야 한다면 awk
polledName에 대한 변수를 설정/설정 해제하세요.
awk -F'[":]' '$2 == "id" {if(lf) print "" ; printf("pri,%s,",$5); lf=1;}
$2 == "name" {printf("%s,",$5)}
$2 == "objectId" {gsub(" ","",$4); printf "%s", $4}
$2 == "polledName" {print $5; lf=0; }
END {if(lf) print "" ;}'
이것은 기본적으로 약간 확장된 코드입니다. 제가 추가한 내용은 다음과 같습니다.
- "id"가 있는 줄은
if(lf) print "" ;
새 줄을 인쇄합니다(lf
0이 아닌 경우)lf=1
.lf
- "polledName"이 포함된 선택적 행:
lf=0;
행이 발견되면 lf를 지웁니다. - 주석별로 사용됩니다
print ""
(print
인수 없이는 현재/마지막 줄이 인쇄됩니다). - $4에 추가된
gsub(" ","",$4);
스트립 공백 (구분 기호가 공백이 아니기 때문에 공백이 보존됨)
이는 awk
json(또는 xml) 파일을 구문 분석하기에는 좋지 않은 솔루션입니다.
이 json 파일을 생성한 프로그램에 따라 다르며 특히 폐쇄된 서버나 장치에 있는 경우 필드 순서가 변경될 수 있습니다.
답변3
줄 순서가 다르거나 다르거나 추가 줄이 손실될 수 있더라도 awk를 사용하세요.
$ awk -F'(^ *")|("?,?$)|(" : "?)' -v OFS=',' '
/}, {/ {
if ( NR>1 ) {
print "pri", f["id"], f["name"], f["objectId"], f["polledName"]
}
delete f
next
}
{ f[$2] = $3 }
' file
pri,1,host1,0001,192.168.1.1
pri,2,host2,0002,192.168.1.2
pri,3,host3,0003,
pri,4,host4,0004,192.168.1.3
위의 작동 방식은 행을 읽을 때마다 f[]
각 레이블(예: objectId
)을 동일한 행의 관련 값(예: )에 매핑한 다음 이를 각 청크의 끝(즉, 표시될 때)에 인쇄하는 배열을 만드는 것입니다. ) 배열의 내용입니다.002
tag : value
}, {
이와 같은 태그 값의 배열을 생성하는 것은 값을 인쇄하는 것보다 이런 종류의 문제를 해결하는 더 나은 일반적인 방법입니다. 왜냐하면 이는 입력의 태그 순서와 무관하기 때문입니다. 출력하고 배열 값의 저장소를 사용하여 조건을 테스트하고 현재 인쇄 블록에서 조치를 취할 수 있습니다.
if ( f["objectId"] > 27 ) print "The objectId is too big for name", f["name"]
if ( !("polledName" in f) ) print "polledName missing for ID", f["id"]
if ( f["objectId"] ~ /7/) && (f["id"] !~ /7/) ) {
printf "objectId %s vs id %s mismatch\n", f["objectId"], f["id"]
}
또는 귀하가 관심을 가질 만한 실제 [조합] 조건.
또는 각 블록의 행 순서가 모든 블록에서 일관되게 보장되는 경우 예에 표시된 대로 다중 문자 RS에 GNU awk를 사용할 수 있습니다.
$ awk -v RS='}, {\n' -F'("?,?\n)|(" : "?)' -v OFS=',' '
NR>1 { print "pri", $2, $4, $6, $8 }
' file
pri,1,host1,0001,192.168.1.1
pri,2,host2,0002,192.168.1.2
pri,3,host3,0003,
pri,4,host4,0004,192.168.1.3
printf $4
코드 등의 경우 - printf input_data
입력 데이터에 printf 형식 문자가 포함되어 있으면 실패하므로 절대 이 작업을 수행 하지 마십시오 . printf "%s", input_data
예를 들어 .printf "%s", $4
또한 awk를 사용하면 sed가 필요하지 않으므로 이 작업을 수행하는 경우 잘못된 작업을 수행하는 것입니다.