Regex sed कमांड के साथ json टेक्स्ट पार्स करने के लिए


15

मेरे पास यह पाठ है:

{
    "buildStatus" : {
        "status" : "ERROR",
        "conditions" : [{
                "status" : "OK",
                "metricKey" : "bugs"
            }, {
                "status" : "ERROR",
                "metricKey" : "test_success_density"
            }, {
                "status" : "OK",
                "metricKey" : "vulnerabilities"
            }
        ],
        "periods" : []
    }
}

मैं बिल्डस्टैटस की समग्र स्थिति निकालना चाहता हूं, अर्थात अपेक्षित आउटपुट "ERROR" था

"buildStatus" : {
    "status" : "ERROR",
    ....
}

मैंने नीचे दिए गए sed अभिव्यक्ति की कोशिश की, लेकिन यह काम नहीं कर रहा है, यह रिटर्न करता है OK:

status= sed -E 's/.*\"buildStatus\":.*\"status\":\"([^\"]*)\",.*/\1/' jsonfile

मैं क्या गलत कर रहा हूं?

जवाबों:


16

नियमित अभिव्यक्ति के साथ JSON या XML जैसी जटिल नेस्टेड डेटा संरचनाओं को पार्स न करें, एक उचित JSON पार्सर का उपयोग करें, जैसे jshon

पहले आपको इसे स्थापित करने की आवश्यकता है:

sudo apt-get install jshon

फिर आपको इसे मानक इनपुट के माध्यम से पार्स करने के लिए JSON डेटा प्रदान करना होगा, ताकि आप या तो एक पाइप ( |) के साथ किसी अन्य कमांड के आउटपुट को रीडायरेक्ट कर सकें या एक फ़ाइल को इसे रीडायरेक्ट कर सकें ( < filename)।

इस तरह आप जिस डेटा को देखना चाहते हैं उसे निकालने के लिए तर्कों की आवश्यकता है:

jshon -e "buildStatus" -e "status" -u
  • -e "buildStatus" शीर्ष स्तर के शब्दकोश से "buildStatus" सूचकांक के साथ तत्व उठाता है।
  • -e "status" दूसरे स्तर के शब्दकोश से "स्टेटस" इंडेक्स वाले तत्व को ऊपर उठाया गया।
  • -u JSON से चयनित डेटा को सादे डेटा में कनवर्ट करता है (यानी यहां यह स्ट्रिंग के आसपास के उद्धरण हटाता है)

तो आपके द्वारा चलाए जा रहे डेटा के आधार पर आपके द्वारा चलाए जाने वाले आदेश पर निर्भर करता है:

jshon -e "buildStatus" -e "status" -u < YOUR_INPUT_FILE
YOUR_JSON_PRODUCING_COMMAND | jshon -e "buildStatus" -e "status" -u

इसके बारे में अधिक जानने के लिए jshon, आप ऑनलाइन या यहाँ टाइप करके इसका मेन्यू पढ़ सकते हैं man jshon


6
वहाँ भी है jq:jq -r .buildStatus.status
मूरू


@HTNW मैं, कि इस सवाल का जवाब कभी नहीं पसंद किया है क्योंकि "एकल एक्सएमएल खुला टैग" (जो क्या सवाल पूछने है) है एक नियमित रूप से भाषा (और आप सिद्धांत के निर्माण में regexes का उपयोग करके एक पूर्ण XML पार्सर टैग, टिप्पणियाँ, cdata मिलान करने के लिए कर सकता है वर्गों, और नेस्टेड संदर्भ को संभालने के लिए एक साधारण स्टैक का उपयोग करते हुए)। हालांकि, JSON में सबसे 'दिलचस्प' नियमित भाषा एक स्ट्रिंग शाब्दिक है।
रैंडम 832

10

नौकरी के लिए jq:

jq -r '.["buildStatus"]["status"]' file.json

इसे छोटा किया जा सकता है:

jq -r '.buildStatus.status' file.json

-r( --raw-output) स्ट्रिंग के बिना jsonस्ट्रिंग को आउटपुट करता है अर्थात बिना उद्धरण के।

उदाहरण:

% cat file.json                   
{
    "buildStatus" : {
        "status" : "ERROR",
        "conditions" : [{
                "status" : "OK",
                "metricKey" : "bugs"
            }, {
                "status" : "ERROR",
                "metricKey" : "test_success_density"
            }, {
                "status" : "OK",
                "metricKey" : "vulnerabilities"
            }
        ],
        "periods" : []
    }
}

% jq -r '.["buildStatus"]["status"]' file.json
ERROR

% jq -r '.buildStatus.status' file.json       
ERROR

यदि पहले से स्थापित नहीं है, तो इसे स्थापित करें (ब्रह्मांड भंडार में उपलब्ध):

sudo apt-get install jq 

8

जैसा कि उल्लेख किया गया है, जटिल संरचित डेटा को पार्स करना उपयुक्त एपीआई के साथ बेहतर है। पायथन के पास इसके लिए jsonमॉड्यूल है, जिसे मैं व्यक्तिगत रूप से अपनी लिपियों में बहुत अधिक उपयोग करता हूं, और यह उन इच्छित फ़ील्ड को निकालने के लिए काफी आसान है जो आप चाहते हैं:

$ python -c 'import sys,json;print json.load(sys.stdin)["buildStatus"]["status"]' <  input.txt
ERROR

यहाँ क्या होता है कि हम इनपुट फ़ाइल को अजगर के स्टड पर रीडायरेक्ट करते हैं, और उसी के साथ पढ़ते हैं json.load()। कुंजी "बिल्डस्टैटस" के साथ एक अजगर शब्दकोश बन जाता है, और इसमें "स्थिति" कुंजी के साथ एक और अजगर शब्दकोष होता है। इस प्रकार, हम केवल एक शब्दकोश में एक कुंजी के मूल्य को प्रिंट कर रहे हैं जो दूसरे शब्दकोश में संग्रहीत है। काफी सरल।

सादगी के अलावा, एक और लाभ यह है कि अजगर और यह एपीआई सभी पूर्वस्थापित हैं और डिफ़ॉल्ट रूप से उबंटू के साथ आते हैं।


6

आप वास्तव में ऐसा कर सकते हैंsed , लेकिन मैं आपसे एक अधिक परिष्कृत भाषा का उपयोग करने का आग्रह करता हूं जिसमें JSON डेटा को संभालने के लिए उपकरण लिखे गए हैं। उदाहरण के लिए, आप पर्ल या अजगर की कोशिश कर सकते हैं।

अब, आपके सरल उदाहरण में, आप जो चाहते हैं, वह पहली घटना है "status", इसलिए आप ऐसा कर सकते हैं:

$ sed -nE '/status/{s/.*:\s*"(.*)",/\1/p;q}' file.json 
ERROR

-nमुद्रण से बचने के लिए चाल का उपयोग किया जाता है, फिर यदि रेखा मेल खाती है status( /status/), तो आप सब कुछ हटा देते हैं, लेकिन जिस भाग को आप चाहते हैं s/.*:\s*"(.*)",/\1/, pलाइन और quit को रेंट करें।


व्यक्तिगत रूप से, मुझे यह समान grep कमांड बहुत सरल लगता है:

$ grep -m1 -oP '"status"\s*:\s*"\K[^"]+' file.json 
ERROR

या यह एक:

$ perl -ne 'if(s/.*"status"\s*:\s*"([^"]+).*/$1/){print;exit}' file.json 
ERROR

हालांकि, यदि आप JSON फ़ाइलों को पार्स करने की योजना बनाते हैं, तो इसे मैन्युअल रूप से करने का प्रयास न करें। एक उचित JSON पार्सर का उपयोग करें।


या यह एक:grep -m 1 status file.json | tr -cd '[[:alnum:]]:' | cut -f2 -d':'
slowko

1
@ user1876040 आपका स्वागत है। कृपया उत्तर में से एक को स्वीकार करने के लिए याद रखें (मैं बाइटस्मैंडर की सलाह देता हूं , उसका एक बेहतर समाधान है) ताकि प्रश्न को उत्तर के रूप में चिह्नित किया जा सके)।
टेराडन

6

यह कहते हुए कि आपको उपयोग नहीं करना चाहिएsed (मुझे लगता है कि किसी ने मुझे अनिवार्य कैविटी लिखने के लिए नहीं लिखा है) लेकिन, अगर आपको अगली पंक्ति में कुछ खोजने की जरूरत है buildStatusजैसा कि आप अपने स्वयं के प्रयास में कर रहे हैं, तो आपको sedपढ़ने के लिए बताने की आवश्यकता है Nकमांड के साथ अगली पंक्ति

$ sed -rn '/buildStatus/N;s/.*buildStatus.*\n.*: "(.*)",/\1/p' file
ERROR

टिप्पणियाँ:

  • -n जब तक हम इसके बारे में नहीं पूछेंगे, तब तक कुछ भी न छापें
  • -rERE (समान -E) का उपयोग करें
  • /buildStatus/N इस पैटर्न को खोजें और अगली पंक्ति भी पढ़ें
  • s/old/new/के oldसाथ बदलेंnew
  • .* लाइन पर किसी भी वर्ण का कोई भी संख्या
  • \n नई पंक्ति
  • : "(.*)",: "और के बीच होने वाले किसी भी वर्ण को बचाएं",
  • \1 सहेजे गए पैटर्न का संदर्भ
  • p हमारे द्वारा काम किए गए भाग को प्रिंट करें

0

क्यों sedऔर इसी तरह की टेक्स्ट स्ट्रीम प्रोसेसिंग टूल की एक विशिष्ट व्याख्या है कि JSON और XML जैसे संरचित डेटा को पार्स करने के लिए अच्छी तरह से सुसज्जित नहीं है। मेरे पास उस हाथ पर नहीं है, लेकिन यह वहां से बाहर है, और मुझे विश्वास है कि बिंदु यह है कि सभी में आवश्यक अभिव्यक्तियाँ हैं, लेकिन शायद स्थितियों में से सबसे कम जल्दी से बहुत जटिल हो जाते हैं, जबकि संरचना को पार्स करने के लिए विशेष रूप से निर्मित वैकल्पिक उपकरण अधिक हैं एक ही पार्सिंग में सुरुचिपूर्ण, पठनीय और कुशल।

जैसे मौरू ने एक टिप्पणी में कहा है , jqनौकरी के लिए सही उपकरण होना चाहिए। मैं इसके लिए व्यक्तिगत रूप से वाउचर भी कर सकता हूं, यह देखने के लिए बहुत उत्साहित है कि इसे कई बार बदला गया है जहां मैंने एक ही डेटा को लगभग नहीं या बोझिल सफलता के लिए पार्स करने की कोशिश की है। यहां तक ​​कि इसमें स्वरूपण और अन्यथा आउटपुट को नियंत्रित करने की क्षमता के बारे में एक बड़ा शामिल है। मैं इसे jsontoolएक कारण या अधिक के लिए पसंद करता हूं जिसे मैं वर्तमान में भूल जाता हूं।

बाइट कमांडरjshon में सिफारिश करने लगता है एक और जवाब । मैंने उस टूल का उपयोग नहीं किया है, लेकिन यह मुझे xmlstarletऔर इसके सिंटैक्स की याद दिलाता है , आउटपुट के लिए कुछ अनुकूलन प्रस्तुति के साथ भी।



3
jsontoolओपी के विशिष्ट मामले के लिए कैसे इस्तेमाल किया जा सकता है, इसका उदाहरण दिखाते हुए अपने उत्तर में सुधार करने पर विचार करें
सेर्गिए कोलोडियाज़नी

Lol @muru, सही है, कि Regex के साथ XML / JSON को पार्स करने से उपयोग करने की कोशिश करने वाली पोस्ट में से एक है! मैं इस बात की अधिक अनुशंसा jqकर रहा था कि मुरु और हेमायल का वर्णन है कि पहले से ही निर्वासित हैं, और सिर्फ इसके पीछे तर्क पोस्ट कर रहे हैं: askubuntu.com/a/863948/230721
Pysis

0

सिर्फ एक अन्य Json उपकरण जिसे json कहा जाता है ( https://github.com/trentm/json )

$ json buildStatus.status < file.json
ERROR

यह केस स्टडी भ्रामक है: ऐसा लगता है कि उपकरण काम नहीं कर रहे हैं। आप jsonjson फ़ाइलों को बदलने के लिए भी उपयोग कर सकते हैं :

$ json -e 'this.buildStatus.status="not error"' < file.json > new.json

या और भी...

$ json -e 'this.buildStatus.status="no errors"' < file.json | json -e 'this.buildStatus.status
no errors

प्रलेखन: http://trentm.com/json/


यदि स्थापित नहीं है:

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