लिनक्स में शेल स्क्रिप्टिंग के साथ JSON को पार्स कैसे करें?


56

मेरे पास एक JSON आउटपुट है जिसमें से मुझे लिनक्स में कुछ मापदंडों को निकालने की आवश्यकता है।

यह JSON आउटपुट है:

{
        "OwnerId": "121456789127",
        "ReservationId": "r-48465168",
        "Groups": [],
        "Instances": [
            {
                "Monitoring": {
                    "State": "disabled"
                },
                "PublicDnsName": null,
                "RootDeviceType": "ebs",
                "State": {
                    "Code": 16,
                    "Name": "running"
                },
                "EbsOptimized": false,
                "LaunchTime": "2014-03-19T09:16:56.000Z",
                "PrivateIpAddress": "10.250.171.248",
                "ProductCodes": [
                    {
                        "ProductCodeId": "aacglxeowvn5hy8sznltowyqe",
                        "ProductCodeType": "marketplace"
                    }
                ],
                "VpcId": "vpc-86bab0e4",
                "StateTransitionReason": null,
                "InstanceId": "i-1234576",
                "ImageId": "ami-b7f6c5de",
                "PrivateDnsName": "ip-10-120-134-248.ec2.internal",
                "KeyName": "Test_Virginia",
                "SecurityGroups": [
                    {
                        "GroupName": "Test",
                        "GroupId": "sg-12345b"
                    }
                ],
                "ClientToken": "VYeFw1395220615808",
                "SubnetId": "subnet-12345314",
                "InstanceType": "t1.micro",
                "NetworkInterfaces": [
                    {
                        "Status": "in-use",
                        "SourceDestCheck": true,
                        "VpcId": "vpc-123456e4",
                        "Description": "Primary network interface",
                        "NetworkInterfaceId": "eni-3619f31d",
                        "PrivateIpAddresses": [
                            {
                                "Primary": true,
                                "PrivateIpAddress": "10.120.134.248"
                            }
                        ],
                        "Attachment": {
                            "Status": "attached",
                            "DeviceIndex": 0,
                            "DeleteOnTermination": true,
                            "AttachmentId": "eni-attach-9210dee8",
                            "AttachTime": "2014-03-19T09:16:56.000Z"
                        },
                        "Groups": [
                            {
                                "GroupName": "Test",
                                "GroupId": "sg-123456cb"
                            }
                        ],
                        "SubnetId": "subnet-31236514",
                        "OwnerId": "109030037527",
                        "PrivateIpAddress": "10.120.134.248"
                    }
                ],
                "SourceDestCheck": true,
                "Placement": {
                    "Tenancy": "default",
                    "GroupName": null,
                    "AvailabilityZone": "us-east-1c"
                },
                "Hypervisor": "xen",
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/sda",
                        "Ebs": {
                            "Status": "attached",
                            "DeleteOnTermination": false,
                            "VolumeId": "vol-37ff097b",
                            "AttachTime": "2014-03-19T09:17:00.000Z"
                        }
                    }
                ],
                "Architecture": "x86_64",
                "KernelId": "aki-88aa75e1",
                "RootDeviceName": "/dev/sda1",
                "VirtualizationType": "paravirtual",
                "Tags": [
                    {
                        "Value": "Server for testing RDS feature in us-east-1c AZ",
                        "Key": "Description"
                    },
                    {
                        "Value": "RDS_Machine (us-east-1c)",
                        "Key": "Name"
                    },
                    {
                        "Value": "1234",
                        "Key": "cost.centre",
                      },
                    {
                        "Value": "Jyoti Bhanot",
                        "Key": "Owner",
                      }
                ],
                "AmiLaunchIndex": 0
            }
        ]
    }

मैं एक फाइल लिखना चाहता हूं जिसमें हेडिंग जैसे आईडी, टैग जैसे नाम, लागत केंद्र, स्वामी शामिल हैं। और नीचे JSON आउटपुट से कुछ निश्चित मान। यहां दिया गया आउटपुट सिर्फ एक उदाहरण है।

मुझे लगता है कि का उपयोग कर कैसे कर सकते हैं sedऔर awk?

अपेक्षित उत्पादन :

 Instance id         Name                           cost centre             Owner
    i-1234576          RDS_Machine (us-east-1c)        1234                   Jyoti

1
अपने सीएलआई कॉल को अजगर में पाइप करें, सुझाव दिया क्योंकि यह EC2 उदाहरणों का मूल निवासी है। पायथन आसानी से JSON की व्याख्या कर सकता है। एक उदाहरण के लिए नीचे दिया गया उत्तर देखें। बेशक, आप किसी अन्य एसएस भाषा का भी उपयोग कर सकते हैं, लेकिन उन्हें इंस्टॉल की आवश्यकता होगी जबकि पायथन पहले से ही है।
रोबी एवरिल

नोड का उपयोग करने के बारे में कैसे ?
एलिरन मलका

जवाबों:


65

लगभग हर प्रोग्रामिंग भाषा में पार्सर्स की उपलब्धता डेटा-इंटरचेंज फॉर्मेट के रूप में JSON के फायदों में से एक है।

JSON पार्सर को लागू करने की कोशिश करने के बजाय, आप JSON पार्सिंग के लिए निर्मित टूल का उपयोग करके बेहतर कर सकते हैं जैसे कि jq या सामान्य उद्देश्य स्क्रिप्ट भाषा जिसमें JSON लाइब्रेरी हो।

उदाहरण के लिए, jq का उपयोग करके, आप ImageID को उदाहरणों के पहले आइटम से निम्नानुसार खींच सकते हैं:

jq '.Instances[0].ImageId' test.json

वैकल्पिक रूप से, रूबी की JSON लाइब्रेरी का उपयोग करके समान जानकारी प्राप्त करने के लिए:

ruby -rjson -e 'j = JSON.parse(File.read("test.json")); puts j["Instances"][0]["ImageId"]'

मैं आपके सभी संशोधित प्रश्नों और टिप्पणियों का उत्तर नहीं दूंगा, लेकिन निम्नलिखित आपको शुरू करने के लिए पर्याप्त रूप से पर्याप्त है।

मान लीजिए कि आपके पास एक रूबी स्क्रिप्ट है जो STDIN से पढ़ सकती है और आपके उदाहरण के आउटपुट में दूसरी पंक्ति का उत्पादन कर सकती है [0]। वह स्क्रिप्ट कुछ इस तरह दिख सकती है:

#!/usr/bin/env ruby
require 'json'

data = JSON.parse(ARGF.read)
instance_id = data["Instances"][0]["InstanceId"]
name = data["Instances"][0]["Tags"].find {|t| t["Key"] == "Name" }["Value"]
owner = data["Instances"][0]["Tags"].find {|t| t["Key"] == "Owner" }["Value"]
cost_center = data["Instances"][0]["SubnetId"].split("-")[1][0..3]
puts "#{instance_id}\t#{name}\t#{cost_center}\t#{owner}"

अपने पूरे लक्ष्य को पूरा करने के लिए आप इस तरह की स्क्रिप्ट का उपयोग कैसे कर सकते हैं? ठीक है, मान लीजिए कि आपके पास पहले से ही निम्नलिखित थे:

  • अपने सभी उदाहरणों को सूचीबद्ध करने के लिए एक कमांड
  • अपनी सूची में किसी भी उदाहरण के लिए ऊपर दिए गए आदेश को प्राप्त करने और इसे STDOU में आउटपुट करने के लिए एक कमांड

इन उपकरणों को संयोजित करने के लिए अपने शेल का उपयोग करने का एक तरीका होगा:

echo -e "Instance id\tName\tcost centre\tOwner"
for instance in $(list-instances); do
    get-json-for-instance $instance | ./ugly-ruby-scriptrb
done

अब, हो सकता है कि आपके पास एक ही कमांड हो, जो आपको उस "इंस्टेंस" सरणी में अधिक वस्तुओं के साथ सभी उदाहरणों के लिए एक json बूँद दे। खैर, अगर ऐसा है, तो आपको केवल पहले आइटम का उपयोग करने के बजाय सरणी के माध्यम से पुनरावृति के लिए स्क्रिप्ट को थोड़ा संशोधित करने की आवश्यकता होगी।

अंत में, इस समस्या को हल करने का तरीका, यूनिक्स में कई समस्याओं को हल करने का तरीका है। इसे आसान समस्याओं में तोड़ दें। आसान समस्या को हल करने के लिए उपकरण खोजें या लिखें। उन उपकरणों को अपने शेल या अन्य ऑपरेटिंग सिस्टम सुविधाओं के साथ मिलाएं।

[०] ध्यान दें कि मुझे इस बात का कोई पता नहीं है कि आपको लागत-केंद्र कहाँ से प्राप्त होता है, इसलिए मैंने अभी इसे बनाया है।


मैंने अपनी मशीन पर jq स्थापित किया है। लेकिन मैं नहीं जानता कि कैसे जानकारी प्राप्त करने के लिए। मैं सवाल अपडेट कर रहा
हूं

उसको कैसे करे। आदेश ec2- वर्णन उदाहरण इस तरह से प्रतिक्षेप देता है। यह 1 उदाहरण के लिए डेटा है, 100 उदाहरण हैं। कैसे एक स्क्रिप्ट में ऐसा करने के लिए
user3086014

मेरे पास ai cli टूल्स हैं जो मुझे आउटपुट देते हैं। अब आउटपुट और आवश्यक टैग को पार्स करने का तरीका जो मुझे वास्तव में नहीं पता है
user3086014

2
@ user3086014 मुझे क्षमा करें, लेकिन मैं इस उत्तर में अधिक काम नहीं करूंगा। मेरे पास मौजूद रूबी उदाहरण पर एक नज़र डालें। यह आपको एक अच्छी जगह देनी चाहिए कि आप जिस JSON को चाहते हैं उसके विभिन्न हिस्सों से टैग कैसे प्राप्त करें।
स्टीवन डी

Json टूल्स उपलब्ध गुड़ के मोल्टिट में मेरा पसंदीदा stedolan.github.io/jq/manual है । एसटीडी वितरण में भी उपलब्ध है। परीक्षण फ़िल्टर के लिए एक खेल का मैदान jqplay.org/jq?q=.&j=%22Hello%%%worldworld
lrkwz

15

उस डेटा को पार्स करने के लिए आप पायथन लिपि का उपयोग कर सकते हैं। मान लें कि आपके पास JSON डेटा है जैसे कि फाइलों में सरणियाँ array1.json, array2.jsonऔर इसी तरह।

import json
import sys
from pprint import pprint

jdata = open(sys.argv[1])

data = json.load(jdata)

print "InstanceId", " - ", "Name", " - ", "Owner"
print data["Instances"][0]["InstanceId"], " - " ,data["Instances"][0]["Tags"][1]["Value"], " - " ,data["Instances"][0]["Tags"][2]["Value"] 

jdata.close()

और फिर बस चलाएं:

$ for x in `ls *.json`; do python parse.py $x; done
InstanceId  -  Name  -  Owner
i-1234576  -  RDS_Machine (us-east-1c)  -  Jyoti Bhanot

मैंने आपके डेटा में लागत नहीं देखी है, इसीलिए मैंने इसे शामिल नहीं किया।

टिप्पणियों में चर्चा के अनुसार, मैंने parse.py स्क्रिप्ट अपडेट की है:

import json
import sys
from pprint import pprint

jdata = sys.stdin.read()

data = json.loads(jdata)

print "InstanceId", " - ", "Name", " - ", "Owner"
print data["Instances"][0]["InstanceId"], " - " ,data["Instances"][0]["Tags"][1]["Value"], " - " ,data["Instances"][0]["Tags"][2]["Value"] 

आप निम्न आदेश चलाने का प्रयास कर सकते हैं:

#ec2-describe-instance <instance> | python parse.py

लेकिन यह सिर्फ एक सरणी है कमांड द्वारा लौटाए गए समान एरे हैं। ऐसा कैसे करें
user3086014

और यह डेटा रन-टाइम पर ec2-description इंस्टेंस कमांड द्वारा जनरेट किया जाता है। कैसे संभालना है
user3086014

मैंने इस पाइथन स्क्रिप्ट को थोड़ा संशोधित किया है: import json from pprint import pprint jdata = open('example.json') data = json.load(jdata) print "InstanceId", " - ", "Name", " - ", "Owner" print data["Instances"][0]["InstanceId"], " - " ,data["Instances"][0]["Tags"][1]["Value"], " - " ,data["Instances"][0]["Tags"][2]["Value"] jdata.close() यदि आपके पास array1.json, array2.json, ... इत्यादि जैसी फाइलों में सरणियों से सभी json डेटा हैं, तो आप इसे इस तरह चलाने का प्रयास कर सकते हैं: # for x in ls * .json; do python parse.py $x; done
रॉबर्ट जोन्सी

आप स्वयं उत्तर को अपडेट कर सकते हैं। यह पठनीय नहीं है
user3086014

मैं भी arrays.100 इस तरह के arrays है
user3086014

9

निम्नलिखित jq कोड:

.Instances[] | (.Tags | map(.value=.Value | .key=.Key) | from_entries) as $tags | "\(.InstanceId) | \($tags.Name) | \($tags["cost.centre"]) | \($tags.Owner)"

जैसे इस्तेमाल किया:

json_producer | jq -r '<jq code...>'

उत्पादन होगा:

i-1234576 | RDS_Machine (us-east-1c) | 1234 | Jyoti Bhanot

कोड को समझने के लिए कुछ संकेत:

  • from_entriesवस्तुओं की एक सरणी लेता है {key:a, value:b}और इसी कुंजी / मूल्य जोड़े ( {a: b}) के साथ एक वस्तु में बदल जाता है ;
  • Keyऔर Valueमें कुंजी Tagsसरणी लोअरकेस परिवर्तित किया था,
  • अंतिम स्ट्रिंग jq के स्ट्रिंग इंटरपोलेशन फीचर का उपयोग करता है। आप इसे आवश्यकतानुसार घुमा सकते हैं।

अधिक जानकारी के लिए, https://stedolan.github.io/jq/ पर jq के ट्यूटोरियल और मैनुअल देखें


1
अब आप (.Tags | map({Value, Key}) | from_entries) as $tagsलोअरकेस में कुंजियों को परिवर्तित किए बिना, टैग के निष्कर्षण को छोटा कर सकते हैं ।
एमएलउर्रन

8

अन्य लोगों ने आपके प्रश्न के लिए सामान्य उत्तर प्रदान किए हैं, जो कि पार्सिंग जोंस के अच्छे तरीकों को प्रदर्शित करते हैं, लेकिन मैं भी आपकी तरह, अन्य पैकेजों के आधार पर बिना किसी awk या sed जैसे कोर टूल का उपयोग करके एक इंस्टेंस उदाहरण id निकालने का तरीका खोज रहा था। इसे पूरा करने के लिए आप अपने aws कमांड को "--आउटपुट = टेक्स्ट" तर्क पास कर सकते हैं जो आपको एक अजीब पार्सबल स्ट्रिंग देगा। इसके साथ आप बस निम्नलिखित जैसे कुछ का उपयोग करके इंस्टेंस आईडी प्राप्त कर सकते हैं ...

aws ec2 run-instances --output text  | awk -F"\t" '$1=="INSTANCES" {print $8}'

3

Jshon कई वितरणों में उपलब्ध है:

$ echo your_JSON|jshon -e Instances -a -e InstanceId -u -p -e Tags -a -e Key -u -p -e Value -u
i-1234576
Description
Server for testing RDS feature in us-east-1c AZ
Name
RDS_Machine (us-east-1c)
cost.centre
1234
Owner
Jyoti Bhanot

गरीब स्पष्टीकरण: -e uuवस्तु निकाल देंगे uu, -aसरणी प्रयोग करने योग्य बनाने के लिए (यकीन नहीं मैं सही ढंग से इस एक phrased लेकिन वैसे भी ...), -uस्ट्रिंग डिकोड जाएगा, -pपिछले आइटम पर वापस जाना होगा (ऐसा लगता है कि -i N, एन किसी भी संख्या जा रहा है, एक ही प्रभाव नहीं है) ।

आपके मामले के आधार पर, आउटपुट को कुछ पोस्ट-ट्रीटमेंट (जैसे आपका, जैसा आप देख सकते हैं) की आवश्यकता हो सकती है।

Jshon JSON कुरूपता के खिलाफ doesn मजबूत लगता है, हालांकि (करीबी ब्रैकेट बंद होने से पहले अल्पविराम के साथ आपका "टैग" एक त्रुटि उठाएगा)।

किसी ने दूसरे धागे में jsawk का उल्लेख किया है , लेकिन मैंने इसका परीक्षण नहीं किया है।



0

यहाँ एक लाइनर सुझाव है:

pr -mt \
 <(grep -o ".*: .*," in.json | grep -iw InstanceId | cut -d: -f2) \
 <(grep -o ".*: .*," in.json | grep -iw Value      | cut -d: -f2) \
 <(grep -o ".*: .*," in.json | grep -iw Key        | cut -d: -f2)

सही नहीं है, लेकिन अगर आप इसे थोड़ा ट्विस्ट करेंगे तो यह काम करेगा।

यह मूल रूप से prप्रति कॉलम प्रत्येक सेट परिणाम को प्रिंट करने के लिए उपयोग करता है। प्रत्येक परिणाम सेट को प्रक्रिया प्रतिस्थापन द्वारा वापस किया जाता है जो JSON फ़ाइल को पार्स करता है और कुंजी के आधार पर मान लौटाता है।

यह वर्णित के समान कार्य करता है: कुंजी-मूल्य सामग्री को देखते हुए, मैं मूल्य द्वारा कुंजी और क्रमबद्ध करके समूह मान कैसे देता हूं?


0

jtcक्ली टूल पर एक नज़र डालें :

यह आपके जेन्स से आवश्यक जानकारी आसानी से निकालने देता है (यह मानकर कि file.json, btw, आपके JSON को ठीक करने की आवश्यकता है, वहाँ कुछ अतिरिक्त कॉमा है):

bash $ cat file.json | jtc -x '<InstanceId>l+0[-1]' -y '[InstanceId]' -y "[Key]:<Name>[-1][Value]" -y "[Key]:<cost.centre>[-1][Value]" -y "[Key]:<Owner>[-1][Value]" | sed 's/"/\\"/g' | xargs -L4 echo
"i-1234576" "RDS_Machine (us-east-1c)" "1234" "Jyoti Bhanot"
bash $ 

-2

jq "." recovery.js | head -n 20

इस तरह से पठनीय कुछ के लिए अपनी जेसन फ़ाइल का अनुवाद करता है:

{
  "संस्करण": [
    "Sessionrestore",
    1
  ],
  "खिड़कियाँ": [
    {
      "टैब": [
        {
          "प्रविष्टियाँ": [
            {
              "url": "http://orf.at/#/stories/2.../"
              "शीर्षक": "news.ORF.at",
              "चारसेट": "यूटीएफ -8",
              "आईडी": 9588,
              "डॉक्सहेलिड": 298,
              "docIdentifier": 10062,
              "दृढ़ता": सच
            },
...

अब किसी भी मानक उपकरण के साथ अपने डेटा को पार्स करना संभव होना चाहिए

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