awk / sed / perl one liner + json 파일에서 속성 줄만 인쇄하는 방법


10

json 파일에서 속성 줄만 인쇄하는 방법

json 파일의 예

{
  "href" : "http://master02:8080/api/v1/clusters/HDP/configurations?type=kafka-env&tag=version1527250007610",
  "items" : [
    {
      "href" : "http://master02:8080/api/v1/clusters/HDP/configurations?type=kafka-env&tag=version1527250007610",
      "tag" : "version1527250007610",
      "type" : "kafka-env",
      "version" : 8,
      "Config" : {
        "cluster_name" : "HDP",
        "stack_id" : "HDP-2.6"
      },
      "properties" : {
        "content" : "\n#!/bin/bash\n\n# Set KAFKA specific environment variables here.\n\n# The java implementation to use.\nexport JAVA_HOME={{java64_home}}\nexport PATH=$PATH:$JAVA_HOME/bin\nexport PID_DIR={{kafka_pid_dir}}\nexport LOG_DIR={{kafka_log_dir}}\nexport KAFKA_KERBEROS_PARAMS={{kafka_kerberos_params}}\nexport JMX_PORT=9997\n# Add kafka sink to classpath and related depenencies\nif [ -e \"/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\" ]; then\n  export CLASSPATH=$CLASSPATH:/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\n  export CLASSPATH=$CLASSPATH:/usr/lib/ambari-metrics-kafka-sink/lib/*\nfi\n\nif [ -f /etc/kafka/conf/kafka-ranger-env.sh ]; then\n. /etc/kafka/conf/kafka-ranger-env.sh\nfi",
        "is_supported_kafka_ranger" : "true",
        "kafka_log_dir" : "/var/log/kafka",
        "kafka_pid_dir" : "/var/run/kafka",
        "kafka_user" : "kafka",
        "kafka_user_nofile_limit" : "128000",
        "kafka_user_nproc_limit" : "65536"
      }
    }
  ]

예상 출력

    "content" : "\n#!/bin/bash\n\n# Set KAFKA specific environment variables here.\n\n# The java implementation to use.\nexport JAVA_HOME={{java64_home}}\nexport PATH=$PATH:$JAVA_HOME/bin\nexport PID_DIR={{kafka_pid_dir}}\nexport LOG_DIR={{kafka_log_dir}}\nexport KAFKA_KERBEROS_PARAMS={{kafka_kerberos_params}}\nexport JMX_PORT=9997\n# Add kafka sink to classpath and related depenencies\nif [ -e \"/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\" ]; then\n  export CLASSPATH=$CLASSPATH:/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\n  export CLASSPATH=$CLASSPATH:/usr/lib/ambari-metrics-kafka-sink/lib/*\nfi\n\nif [ -f /etc/kafka/conf/kafka-ranger-env.sh ]; then\n. /etc/kafka/conf/kafka-ranger-env.sh\nfi",
    "is_supported_kafka_ranger" : "true",
    "kafka_log_dir" : "/var/log/kafka",
    "kafka_pid_dir" : "/var/run/kafka",
    "kafka_user" : "kafka",
    "kafka_user_nofile_limit" : "128000",
    "kafka_user_nproc_limit" : "65536"


답변:


33

Jq JSON 데이터를 처리하기위한 올바른 도구입니다.

jq '.items[].properties | to_entries[] | "\(.key) : \(.value)"' input.json

출력 :

"content : \n#!/bin/bash\n\n# Set KAFKA specific environment variables here.\n\n# The java implementation to use.\nexport JAVA_HOME={{java64_home}}\nexport PATH=$PATH:$JAVA_HOME/bin\nexport PID_DIR={{kafka_pid_dir}}\nexport LOG_DIR={{kafka_log_dir}}\nexport KAFKA_KERBEROS_PARAMS={{kafka_kerberos_params}}\nexport JMX_PORT=9997\n# Add kafka sink to classpath and related depenencies\nif [ -e \"/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\" ]; then\n  export CLASSPATH=$CLASSPATH:/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\n  export CLASSPATH=$CLASSPATH:/usr/lib/ambari-metrics-kafka-sink/lib/*\nfi\n\nif [ -f /etc/kafka/conf/kafka-ranger-env.sh ]; then\n. /etc/kafka/conf/kafka-ranger-env.sh\nfi"
"is_supported_kafka_ranger : true"
"kafka_log_dir : /var/log/kafka"
"kafka_pid_dir : /var/run/kafka"
"kafka_user : kafka"
"kafka_user_nofile_limit : 128000"
"kafka_user_nproc_limit : 65536"

각 키와 값을 큰 따옴표로 묶어야하는 경우 다음 수정을 사용하십시오.

jq -r '.items[].properties | to_entries[]
       | "\"\(.key)\" : \"\(.value | gsub("\n";"\\n"))\","' input.json

출력 :

"content" : "\n#!/bin/bash\n\n# Set KAFKA specific environment variables here.\n\n# The java implementation to use.\nexport JAVA_HOME={{java64_home}}\nexport PATH=$PATH:$JAVA_HOME/bin\nexport PID_DIR={{kafka_pid_dir}}\nexport LOG_DIR={{kafka_log_dir}}\nexport KAFKA_KERBEROS_PARAMS={{kafka_kerberos_params}}\nexport JMX_PORT=9997\n# Add kafka sink to classpath and related depenencies\nif [ -e "/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar" ]; then\n  export CLASSPATH=$CLASSPATH:/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\n  export CLASSPATH=$CLASSPATH:/usr/lib/ambari-metrics-kafka-sink/lib/*\nfi\n\nif [ -f /etc/kafka/conf/kafka-ranger-env.sh ]; then\n. /etc/kafka/conf/kafka-ranger-env.sh\nfi",
"is_supported_kafka_ranger" : "true",
"kafka_log_dir" : "/var/log/kafka",
"kafka_pid_dir" : "/var/run/kafka",
"kafka_user" : "kafka",
"kafka_user_nofile_limit" : "128000",
"kafka_user_nproc_limit" : "65536",

jq순진한 문자열 연산 대신 구문 인식 도구 ( )를 사용하는 것이 좋습니다. 그러나 순진한 문자열 연산을 사용하여 출력을 위해 (제한된) 이스케이프 시퀀스 처리를 수행합니다. 그건 좋은 생각이 아닌 것 같습니다. jq출력 값을 올바르게 벗어날 수있는 방법이 있어야합니다.
Daniel Pryden

@DanielPryden, No. jq출력 값 (예 @text: @sh등) 을 올바르게 이스케이프 처리하는 방법이 있지만 이 경우에는 도움이되지 않습니다.
RomanPerekhrest

: JSON 개체와 용도 등의 잎 속성 값이 원치 않는 괄호과 공백을 제거하기 위해서 나오지 것을 변종jq '.items[].properties' input.json | sed -n 's/^\s\+//p'
조 리 - Moyet을

예상 결과로 ","가 출력에 나타나지 않는 이유는 무엇입니까?
yael

내 "예상 된 결과"를 보시겠습니까? 예상 한 결과에 따라 답변을 편집 할 수 있습니까?
yael

27

구조화되지 않은 도구로 구조화 된 데이터를 분석하는 습관을 들이지 마십시오. 당신이 XML을 구문 분석하는 경우, JSON, 등등 YAML은, 적어도 AWK에 대한,보다 적절한 형태로 구조화 된 데이터를 변환하기 위해, 특정 파서를 사용 sed, grep

이 경우 gron크게 도움 이 될 것입니다.

$ gron yourfile | grep -F .properties.
json.items[0].properties.content = "\n#!/bin/bash\n\n# Set KAFKA specific environment variables here.\n\n# The java implementation to use.\nexport JAVA_HOME={{java64_home}}\nexport PATH=/usr/lib/ccache:/home/steve/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/bin\nexport PID_DIR={{kafka_pid_dir}}\nexport LOG_DIR={{kafka_log_dir}}\nexport KAFKA_KERBEROS_PARAMS={{kafka_kerberos_params}}\nexport JMX_PORT=9997\n# Add kafka sink to classpath and related depenencies\nif [ -e \"/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\" ]; then\n  export CLASSPATH=:/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\n  export CLASSPATH=:/usr/lib/ambari-metrics-kafka-sink/lib/*\nfi\n\nif [ -f /etc/kafka/conf/kafka-ranger-env.sh ]; then\n. /etc/kafka/conf/kafka-ranger-env.sh\nfi";
json.items[0].properties.is_supported_kafka_ranger = "true";
json.items[0].properties.kafka_log_dir = "/var/log/kafka";
json.items[0].properties.kafka_pid_dir = "/var/run/kafka";
json.items[0].properties.kafka_user = "kafka";
json.items[0].properties.kafka_user_nofile_limit = "128000";
json.items[0].properties.kafka_user_nproc_limit = "65536";

( | cut -d. -f4- | gron --ungron아직 유효한 JSON 임에도 불구하고 원하는 출력에 매우 가까운 것을 얻기 위해 이것을 후 처리 할 수 ​​있습니다 .)

jq이다 또한 적절한 .


2

에서 Sed의 - 브루스 바넷에 의해 소개 및 튜토리얼 :

sed -n '/properties/,/}$/ {
            /properties/n
            /}$/ !p
        }' FILE.json

보다 정확한 일치를 위해 추가 공백이있는 괄호 줄 닫기를 관리 할 수 ​​있습니다.

sed -E -n '/"properties" : {/,/^[[:blank:]]*}[[:blank:]]$/ {
               /"properties" : {/n
               /^[[:blank:]]*}[[:blank:]]$/ !p
           }' FILE.json

JSON에 익숙하지 않지만 /}/보다 안전합니다 /}$. 후자는 어쨌든 이점이없는 것 같습니다.
Hauke ​​Laging

1
@HaukeLaging 줄 끝 마커가 없으면 이미 어딘가에 있는 content줄 과 일치합니다 }.
nohillside

5
가능하더라도 예제 파일 에서만 작동 합니다. 구조화 된 데이터를 구문 분석하려면이를 위해 설계된 것을 사용해야합니다. jq, xpath, yq, xq 등이 될 것입니다. 그것은 라인 지향 도구로 구문 분석하면 결국 뒤에서 디버깅하고 매우 쉽지 않을 수 있기 때문입니다.
nert

예를 들어 'href'필드 중 하나에 'properties'라는 단어가 포함되어 있으면 어떻게됩니까?
Stig Hemmer

1
@StigHemmer 그래서 두 번째 예제에서 패턴을 확장했습니다. 그러나 나는 완전히 사용에 동의 gron하거나하는 것이 jq더 나은 방법입니다.
nohillside

2

sed짧막 한 농담. 정규식 properties(예 : "속성"을 포함하는 행)과 정규식 ^ *}(예 : 0 개 이상의 공백으로 시작하고 그 뒤에 "}"및 행 끝)이있는 행을 인쇄하십시오.

sed -n '/properties/,/^ *}$/{//!p}' file.json

awk 짧막 한 농담.

awk '/^ *}/{s=0}/properties/{getline;s=1}s' file.json

패턴 일치가 어떻게 작동하는지 설명 할 수 있습니다.
vfbsilva

1
이것은 예제 파일에서 작동하지만 JSON을 이해하지 못하는 도구로 구문 분석하려고하면 위험합니다. 예를 들어 'href'필드 중 하나에 'properties'라는 단어가 포함되어 있으면 어떻게됩니까? 가장 인기있는 답변과 같은 JSON 인식 도구는 버그가 적습니다.
Stig Hemmer

3
동의하고 위험합니다. 그러나 OP는 특히 sed / awk / perl을 사용하는 단일 라이너 솔루션을 원했습니다. 내가 주신 대답은이 모든 기준을 충족합니다.
steve

무슨 //!p뜻입니까? 일치하는 항목 중 하나가 아닌 경우 인쇄합니까?
David Conrad

1
아, //알았어, 마지막 정규 표현식을 반복 !하지 말고 p인쇄하십시오. 좋은.
David Conrad

1

태그가 붙어 perl있으며 perl아직 답변이 없으므로 칩을 넣을 것입니다.

정규 표현식이나 다른 '구조화되지 않은'파서를 사용하지 마십시오. perl가지고 JSON그것 모듈. ( JSON::PP5.14 이후 핵심 부분 임)

#!/usr/bin/env perl

use strict;
use warnings;
use JSON;
use Data::Dumper;

my $str = do { local $/; <DATA> };

my $json = decode_json ( $str );

my $properties = $json -> {items} -> [0] -> {properties}; 

#dump the whole lot:
print Dumper $properties;


# or iterate
foreach my $key ( sort keys %$properties ) { 
   print "$key => ", $properties -> {$key},"\n";
}


__DATA__
{
  "href" : "http://master02:8080/api/v1/clusters/HDP/configurations?type=kafka-env&tag=version1527250007610",
  "items" : [
    {
      "href" : "http://master02:8080/api/v1/clusters/HDP/configurations?type=kafka-env&tag=version1527250007610",
      "tag" : "version1527250007610",
      "type" : "kafka-env",
      "version" : 8,
      "Config" : {
        "cluster_name" : "HDP",
        "stack_id" : "HDP-2.6"
      },
      "properties" : {
        "content" : "\n#!/bin/bash\n\n# Set KAFKA specific environment variables here.\n\n# The java implementation to use.\nexport JAVA_HOME={{java64_home}}\nexport PATH=$PATH:$JAVA_HOME/bin\nexport PID_DIR={{kafka_pid_dir}}\nexport LOG_DIR={{kafka_log_dir}}\nexport KAFKA_KERBEROS_PARAMS={{kafka_kerberos_params}}\nexport JMX_PORT=9997\n# Add kafka sink to classpath and related depenencies\nif [ -e \"/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\" ]; then\n  export CLASSPATH=$CLASSPATH:/usr/lib/ambari-metrics-kafka-sink/ambari-metrics-kafka-sink.jar\n  export CLASSPATH=$CLASSPATH:/usr/lib/ambari-metrics-kafka-sink/lib/*\nfi\n\nif [ -f /etc/kafka/conf/kafka-ranger-env.sh ]; then\n. /etc/kafka/conf/kafka-ranger-env.sh\nfi",
        "is_supported_kafka_ranger" : "true",
        "kafka_log_dir" : "/var/log/kafka",
        "kafka_pid_dir" : "/var/run/kafka",
        "kafka_user" : "kafka",
        "kafka_user_nofile_limit" : "128000",
        "kafka_user_nproc_limit" : "65536"
      }
    }
  ]
}

당연히 실제 사용 시나리오가 STDIN아닌 파일 이름을 읽 거나 파일 이름을 읽습니다 DATA.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.