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"
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",
非構造化ツールで構造化データを解析する習慣をつけないでください。 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であるにもかかわらず、目的の出力に非常に近いものを取得できます。)
From Sed-紹介とチュートリアル、Bruce Barnett :
sed -n '/properties/,/}$/ {
/properties/n
/}$/ !p
}' FILE.json
より正確に一致させるため、および追加の空白を使用して括弧線を閉じる場合にも使用できます
sed -E -n '/"properties" : {/,/^[[:blank:]]*}[[:blank:]]$/ {
/"properties" : {/n
/^[[:blank:]]*}[[:blank:]]$/ !p
}' FILE.json
sed
1つのライナー。正規表現properties
(「プロパティ」を含む行)と正規表現^ *}
(つまり、0個以上のスペースで始まり、「}」と行末)の間の行を出力します。
sed -n '/properties/,/^ *}$/{//!p}' file.json
awk
1つのライナー。
awk '/^ *}/{s=0}/properties/{getline;s=1}s' file.json
Perl
というタグが付けられており、Perl
の答えはまだないので、チップインします。
正規表現や他の「非構造化」パーサーを使用しないでください。 Perl
にはJSON
モジュールがあります。 (JSON::PP
は5.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
またはファイル名から読み取ります。