awk/sed/perl один лайнер + як друкувати лише рядки властивостей з файлу json

як друкувати лише рядки властивостей з файлу 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"
9
Пов'язані також: відповідати відкритим тегам, за винятком міток, що містять xhtml "" stackoverflow.com/questions/1732348/…
додано Автор ZebraSocks, джерело

5 Відповіді

Jq is the right tool for processing JSON data:

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",
33
додано
@DanielPryden, No. Хоча jq має кілька способів правильно уникнути значення для виводу (наприклад, @text , @sh і т.д.), у цьому випадку це не допоможе.
додано Автор Mayo, джерело
@yael, що саме означає?
додано Автор Mayo, джерело
@yael, просто додайте кому перед останньою подвійною цитатою, побачите моє оновлення (хоча останній рядок також матиме кома)
додано Автор Mayo, джерело
@yael, так, замість того, щоб постійно розширювати та збільшувати вхідний вміст, ви можете ініціювати нове питання з новими умовами
додано Автор Mayo, джерело
Ви виступаєте за використання синтаксично орієнтованого інструменту ( jq ), а не наївних операцій рядка, що є хорошим, але тоді ви використовуєте наївну операцію, щоб зробити (обмежена) обробку послідовності виходів для виводу. Це не здається мені гарною ідеєю. jq має правильно уникнути значення для виводу, чи не так?
додано Автор weiyin, джерело
Варіант, який залишає значення властивостей як об'єкти JSON і використовує sed для видалення небажаних фігурних фігур і фігур: jq '.items []. Properties' input.json | sed -n 's/^ s//p'
додано Автор firo, джерело
його видалили зворотну косу риску перед подвійною цитатою, наприклад, якщо у нас є файл
додано Автор brismuth, джерело
@RomanPerekhrest, якщо ви хочете, я можу поставити це питання "вище" з іншою темою?
додано Автор brismuth, джерело
@RomanPerekhrest Я бачу іншу проблему з jq -r ' to_entries [] | "(". ключ | gsub ("" "" "" "" ")"
додано Автор brismuth, джерело
Добре дякую я буду, кілька хвилин я послав його
додано Автор brismuth, джерело
Я опублікував потік про нове питання
додано Автор brismuth, джерело
у вашому виводі в кінці рядка міститься відсутній роздільник комах "," ви можете побачити мій очікуваний вивід у моєму запиті, що роздільник комами має бути в кінці кожного рядка
додано Автор brismuth, джерело
Ви можете побачити, будь ласка, мій "очікуваний результат", чи можете ви редагувати свою відповідь відповідно до очікуваних результатів?
додано Автор brismuth, джерело
чому "," не відображається у вихідних даних, як очікувані результати?
додано Автор brismuth, джерело

Будь ласка, не використовуйте звичку розбирати структуровані дані за допомогою неструктурованих інструментів. Якщо ви аналізуєте 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 is also appropriate.

26
додано

sed one liner. Print lines between regular expression properties (i.e line containing "properties") and regular expression ^ *} (i.e. line starting with zero or more spaces followed by "}" and end-of-line).

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

awk one liner.

awk '/^ *}/{s=0}/properties/{getline;s=1}s' file.json
2
додано
Погодьтеся, ризиковано. Але ОР спеціально хотів одно-лайнер рішення з використанням sed/awk/perl. Відповідь, яку я дав, відповідає всім цим критеріям.
додано Автор Stanley.Goldman, джерело
Ах, отримали, // повторює останній регулярний вираз, ! не, p друкує. НІЦЕ.
додано Автор Rudi_Birnbaum, джерело
Що означає //! P ? Друк, якщо не одна з речей, які відповідають?
додано Автор Rudi_Birnbaum, джерело
Хоча це працює для наведеного прикладного файлу, ризиковано намагається розібрати JSON за допомогою інструментів, які не розуміють його. Наприклад, що станеться, якщо одне з полів "href" містить слово "властивості"? Це набагато менш схильний до помилок інструмент, який знає JSON, як відповіді на вибір.
додано Автор user3041539, джерело
можливо, ви могли б пояснити, як працює ваш зразок.
додано Автор Srihari Karanth, джерело

Від Сед - Вступ і Підручник Брюса Барнетта :

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

Для більш точного збігу і для того, щоб також подбати про закриття ліній дужок додатковим пробілом, який можна використовувати

sed -E -n '/"properties" : {/,/^[[:blank:]]*}[[:blank:]]$/ {
               /"properties" : {/n
               /^[[:blank:]]*}[[:blank:]]$/ !p
           }' FILE.json
2
додано
@HaukeLaging Без маркера кінця рядка він уже відповідає рядку content , який де-небудь містить } .
додано Автор Lubin, джерело
@StigHemmer Тому я розширив модель у другому прикладі. Але я повністю згоден, що використання gron або jq є кращим підходом.
додано Автор Lubin, джерело
Незважаючи на те, що це можливо, воно, швидше за все, працюватиме тільки з прикладом файлу . Якщо ви хочете розібрати структуровані дані, вам слід скоріше скористатися для цього. Будь то jq, xpath, yq, xq і т. Д. Це тому, що розбір його з лінійно-орієнтованими інструментами в кінцевому підсумку укусить тебе в спину і налагодження, що може бути не дуже просто.
додано Автор Brian MacKenzie, джерело
Я не знайомий з JSON, але, можливо, /}/ безпечніше, ніж /} $ . Останній, мабуть, не має жодних переваг.
додано Автор user32191, джерело
Наприклад, що станеться, якщо одне з полів "href" містить слово "властивості"?
додано Автор user3041539, джерело

Він позначено тегом 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 $/;  };

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 у вашому реальному сценарії використання.

0
додано
ІТ КПІ - JavaScript
ІТ КПІ - JavaScript
504 учасників

співтовариство javascript розробників в Telegram