awk / sed / perl bir astar + nasıl json dosyasından sadece özellikler satırları yazdırılır


10

json dosyasından yalnızca özellikler satırlarını yazdırma

json dosyası örneği

{
  "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"
      }
    }
  ]

beklenen çıktı

    "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"


Yanıtlar:


33

Jq JSON verilerini işlemek için doğru araçtır:

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

Çıktı:

"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"

Her bir anahtarın ve değerin çift tırnak içinde alınmasının gerçekten zorunlu olması durumunda - aşağıdaki değişikliği kullanın:

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

Çıktı:

"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",

jqNaif dize işlemleri yerine sözdizimi kullanan bir araç ( ) kullanarak savunuyorsunuz . Bu benim için iyi bir fikir gibi görünmüyor. jqçıktı değeri düzgün kaçmak için bir yolu olmalı, değil mi?
Daniel Pryden

@DanielPryden, No. rağmen jqdüzgün çıkış için değer kaçmak için bazı yollar var (gibi @text, @shvb), bu bu özel durumda değil bize yardım eder.
RomanPerekhrest

Özellik değerlerini JSON nesneleri olarak bırakan ve istenmeyen parantezleri ve boşlukları ayırmak için sed kullanan bir varyant:jq '.items[].properties' input.json | sed -n 's/^\s\+//p'
Joe Lee-Moyet

beklenen sonuçlarım olarak neden çıktıda "," görünmüyor?
yael

Lütfen "beklenen çıktımı" görebiliyor musunuz, cevabınızı beklenen sonuçlarıma göre düzenleyebilir misiniz?
yael

27

Lütfen yapılandırılmamış araçlarla yapılandırılmış verileri ayrıştırma alışkanlığı edinmeyin. XML ayrıştırma ediyorsanız, JSON, vb YAML, en azından AWK için, daha uygun bir forma yapılandırılmış verileri dönüştürmek için, belirli bir ayrıştırıcı kullanmak sed, grepvb

Bu durumda, gronbüyük ölçüde yardımcı olacaktır:

$ 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 --ungronGeçerli JSON olsa da, istediğiniz çıktıya çok yakın bir şey elde etmek için bunu sonradan işleyebilirsiniz .)

jqolduğu , uygun .


2

Gönderen Sed - Bruce Barnett tarafından An Introduction ve Öğretici :

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

Daha kesin bir eşleşme için ve ayrıca ek boşluk içeren parantez hatlarını kapatmak için kullanabilirsiniz

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

Ben JSON aşina değilim ama belki /}/daha güvenlidir /}$. İkincisinin zaten herhangi bir avantajı yok gibi görünüyor.
Hauke ​​Laging

1
@HaukeLaging Satır sonu işareti olmadan, zaten contentbir }yerde bulunan satırla eşleşiyor .
nohillside

5
Mümkün olsa da, büyük olasılıkla yalnızca örnek dosya üzerinde çalışacaktır . Yapısal verileri ayrıştırmak istiyorsanız, bunun için tasarlanmış bir şey kullanmayı tercih etmelisiniz. Olsun jq, xpath, yq, xq, vb. Çünkü çizgi odaklı araçlarla ayrıştırmak sonunda arkada ısırır ve hata ayıklaması çok kolay olmayabilir.
nert

Örneğin, 'href' alanlarından biri "özellikler" kelimesini içeriyorsa ne olur?
Stig Hemmer

1
@StigHemmer Bu yüzden ikinci örnekte kalıbı genişlettim. Ancak, gronveya yöntemini kullanmanın jqdaha iyi bir yaklaşım olduğunu tamamen kabul ediyorum .
nohillside

2

sedbir astar. Normal ifade properties(yani "özellikler" içeren satır) ve normal ifade ^ *}(yani sıfır veya daha fazla boşlukla başlayan, ardından "}" ve satır sonu ) arasındaki satırları yazdırın .

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

awk bir astar.

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

belki desen eşleştirmenizin nasıl çalıştığını açıklayabilirsiniz.
vfbsilva

1
Bu, verilen örnek dosya için çalışırken, JSON'u anlamayan araçlarla ayrıştırmaya çalışmak risklidir. Örneğin, 'href' alanlarından biri "özellikler" kelimesini içeriyorsa ne olur? En çok oy alan cevaplar gibi JSON kullanan bir araca çok daha az hata eğilimi gösterir.
Stig Hemmer

3
Katılıyorum, riskli. Ancak OP özellikle sed / awk / perl kullanan tek astarlı bir çözüm istedi. Verdiğim cevap tüm bu kriterleri karşılıyor.
steve

Ne anlama //!pgeliyor? Eşleşenlerden biri değilse yazdırın?
David Conrad

1
Ah, anladım //, son normal ifadeyi tekrarlıyor !, pyazdırmıyor. Güzel.
David Conrad

1

Etiketlendi perlve henüz bir perlcevap göremiyorum , bu yüzden devreye gireceğim.

Normal ifadeler veya diğer 'yapılandırılmamış' ayrıştırıcılar kullanmayın. perlvardır JSONonunla modülü. ( JSON::PP5.14'ten beri çekirdeğin bir parçasıdır)

#!/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"
      }
    }
  ]
}

Doğal olarak , gerçek kullanım STDINsenaryounuz yerine bir dosya adı veya dosya adı DATAokurdunuz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.