awk / sed / perl एक लाइनर + कैसे 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"


इसके अलावा संबंधित: stackoverflow.com/questions/1732348/…
कार्तिक

जवाबों:


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सही तरीके से आउटपुट के लिए मूल्य से बचने का एक तरीका होना चाहिए, है ना?
डैनियल प्राइडेन

@DanielPryden, नहीं, हालांकि jqआउटपुट (जैसे @text, @shआदि) के लिए मूल्य को ठीक से भागने के कुछ तरीके हैं , जो इस विशेष मामले में मदद नहीं करेंगे।
रोमनपेरेक्रेस्ट

एक प्रकार जो कि JSON ऑब्जेक्ट्स के रूप में गुण मान छोड़ देता है और अवांछित ब्रेसिज़ और व्हाट्सएप को छीनने के लिए sed का उपयोग करता है:jq '.items[].properties' input.json | sed -n 's/^\s\+//p'
जो ली-मोयेट

क्यों "," अपेक्षित परिणाम के रूप में आउटपुट में प्रकट नहीं होता है?
येल

क्या आप मेरे "अपेक्षित आउटपुट" को देख सकते हैं, क्या आप मेरे अपेक्षित परिणामों के अनुसार अपना उत्तर संपादित कर सकते हैं?
येल

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 से परिचित नहीं हूं, लेकिन शायद इससे /}/अधिक सुरक्षित है /}$। उत्तरार्द्ध को वैसे भी कोई लाभ नहीं है।
हॉउक लागिंग

1
@HaLLaging बिना अंत के लाइन मार्कर के यह पहले से ही उस contentलाइन से मेल खाता है जिसमें }कहीं न कहीं शामिल है।
nohillside

5
हालांकि यह संभव है, यह सबसे अधिक संभावना केवल उदाहरण फ़ाइल पर काम करेगा । यदि आप संरचित डेटा को पार्स करना चाहते हैं, तो आपको इसके लिए डिज़ाइन की गई चीज़ का उपयोग करना चाहिए। यह jq, xpath, yq, xq, आदि हो, क्योंकि लाइन-ओरिएंटेड टूल के साथ इसे पार्स करने से अंततः आपको बैक में डिबगिंग होगी और डीबग करना बहुत आसान नहीं हो सकता है।
nert

उदाहरण के लिए, यदि "href" फ़ील्ड में "गुण" शब्द शामिल है, तो क्या होगा?
स्टिग हेमर

1
@StigHemmer यही कारण है कि मैंने दूसरे उदाहरण में पैटर्न बढ़ाया। लेकिन मैं पूरी तरह से सहमत हूं कि उपयोग करना gronया jqबेहतर दृष्टिकोण है।
nohillside

2

sedएक लाइन। रेगुलर एक्सप्रेशन properties(यानी "गुण" वाली लाइन) और रेगुलर एक्सप्रेशन ^ *}(यानी "}" और एंड-ऑफ-लाइन के बाद शून्य या अधिक स्पेस से शुरू होने वाली लाइन ) के बीच प्रिंट लाइनें ।

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

awk एक लाइन।

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

शायद आप बता सकते हैं कि आपका पैटर्न कैसे मेल खाता है।
vfbsilva

1
जबकि यह दी गई उदाहरण फ़ाइल के लिए काम करता है, यह JSON को ऐसे उपकरणों के साथ पार्स करने का प्रयास कर रहा है जो इसे नहीं समझते हैं। उदाहरण के लिए, यदि "href" फ़ील्ड में "गुण" शब्द शामिल है, तो क्या होगा? यह शीर्ष-मतदान उत्तरों की तरह JSON- जागरूक टूल से बहुत कम बग-रहित है।
स्टिग हेमर

3
सहमत, जोखिम भरा। लेकिन ओपी विशेष रूप से sed / awk / perl का उपयोग करके एक-लाइनर समाधान चाहता था। मैंने जो उत्तर दिया है, वह इन सभी मानदंडों को पूरा करता है।
स्टीव

क्या //!pमतलब है? प्रिंट अगर नहीं है कि चीजों में से एक है?
डेविड कॉनरेड

1
आह, मिल गया, //आखिरी रेगेक्स दोहराता है, !नहीं, pप्रिंट। अच्छा।
डेविड कॉनरेड

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.