निम्नलिखित tocsv
और fromcsv
फ़ंक्शन हेडर से संबंधित आवश्यकता (6) के संबंध में एक जटिलता को छोड़कर बताई गई समस्या का समाधान प्रदान करते हैं। अनिवार्य रूप से, इस आवश्यकता को मैट्रिक्स ट्रांसपोज़िशन चरण जोड़कर यहां दिए गए कार्यों का उपयोग करके पूरा किया जा सकता है।
ट्रांसपोज़िशन चरण जोड़ा गया है या नहीं, यहां लिए गए दृष्टिकोण का लाभ यह है कि JSON कुंजियों या मानों पर कोई प्रतिबंध नहीं है। विशेष रूप से, उनमें पीरियड्स (डॉट्स), न्यूलाइन्स और/या NUL कैरेक्टर हो सकते हैं।
उदाहरण में, वस्तुओं की एक सरणी दी गई है, लेकिन वास्तव में मान्य JSON दस्तावेज़ों की किसी भी धारा का उपयोग tocsv
के इनपुट के रूप में किया जा सकता है।; jq के जादू के लिए धन्यवाद, मूल स्ट्रीम को fromcsv
. द्वारा फिर से बनाया जाएगा (इकाई-दर-इकाई समानता के अर्थ में)।
बेशक, चूंकि कोई CSV मानक नहीं है, इसलिए tocsv
. द्वारा निर्मित CSV फ़ंक्शन को सभी CSV प्रोसेसर द्वारा नहीं समझा जा सकता है। विशेष रूप से, कृपया ध्यान दें कि tocsv
फ़ंक्शन को यहां परिभाषित किया गया है, JSON स्ट्रिंग्स या दो-कैरेक्टरस्ट्रिंग "\n" के प्रमुख नामों में मैप-एम्बेडेड न्यूलाइन्स (यानी, "n" अक्षर के बाद एक शाब्दिक बैकस्लैश); उलटा ऑपरेशन "राउंड-ट्रिप" को पूरा करने के लिए उलटा अनुवाद करता है। आवश्यकता।
(tail
. का उपयोग प्रस्तुति को सरल बनाने के लिए है; समाधान को केवल-jq बनाने के लिए उसे संशोधित करना तुच्छ होगा।)
सीएसवी इस धारणा पर उत्पन्न होता है कि किसी भी मूल्य को किसी फ़ील्ड में शामिल किया जा सकता है जब तक कि (ए) फ़ील्ड उद्धृत किया जाता है, और (बी) फ़ील्ड के भीतर डबल-कोट्स दोगुना हो जाते हैं।
कोई भी सामान्य समाधान जो "राउंड-ट्रिप" का समर्थन करता है, वह कुछ हद तक जटिल है। यहां प्रस्तुत समाधान एक अपेक्षा से अधिक जटिल है, इसका मुख्य कारण यह है कि एक तीसरा कॉलम जोड़ा गया है, आंशिक रूप से पूर्णांक और पूर्णांक-मूल्यवान स्ट्रिंग्स के बीच अंतर करना आसान बनाने के लिए, लेकिन मुख्य रूप से क्योंकि यह आकार -1 और आकार के बीच अंतर करना आसान बनाता है। -2 सरणियाँ jq's--stream
. द्वारा निर्मित हैं विकल्प। कहने की जरूरत नहीं है कि इन मुद्दों को संबोधित करने के अन्य तरीके भी हैं; jq पर कॉलों की संख्या भी कम की जा सकती है।
समाधान को एक परीक्षण स्क्रिप्ट के रूप में प्रस्तुत किया जाता है जो एक टेलिंग टेस्ट केस पर राउंड-ट्रिप आवश्यकता की जांच करता है:
#!/bin/bash
function json {
cat<<EOF
[
{
"a": 1,
"b": [
1,
2,
"1"
],
"c": "d\",ef",
"embed\"ed": "quote",
"null": null,
"string": "null",
"control characters": "a\u0000c",
"newline": "a\nb"
},
{
"x": 1
}
]
EOF
}
function tocsv {
jq -ncr --stream '
(["path", "value", "stringp"],
(inputs | . + [.[1]|type=="string"]))
| map( tostring|gsub("\"";"\"\"") | gsub("\n"; "\\n"))
| "\"\(.[0])\",\"\(.[1])\",\(.[2])"
'
}
function fromcsv {
tail -n +2 | # first duplicate backslashes and deduplicate double-quotes
jq -rR '"[\(gsub("\\\\";"\\\\") | gsub("\"\"";"\\\"") ) ]"' |
jq -c '.[2] as $s
| .[0] |= fromjson
| .[1] |= if $s then . else fromjson end
| if $s == null then [.[0]] else .[:-1] end
# handle newlines
| map(if type == "string" then gsub("\\\\n";"\n") else . end)' |
jq -n 'fromstream(inputs)'
}
# Check the roundtrip:
json | tocsv | fromcsv | jq -s '.[0] == .[1]' - <(json)
यहाँ CSV है जो json | tocsv
, सिवाय इसके कि SO शाब्दिक NULs को अस्वीकार करता प्रतीत होता है, इसलिए मैंने इसे \0
से बदल दिया है :
"path","value",stringp
"[0,""a""]","1",false
"[0,""b"",0]","1",false
"[0,""b"",1]","2",false
"[0,""b"",2]","1",true
"[0,""b"",2]","false",null
"[0,""c""]","d"",ef",true
"[0,""embed\""ed""]","quote",true
"[0,""null""]","null",false
"[0,""string""]","null",true
"[0,""control characters""]","a\0c",true
"[0,""newline""]","a\nb",true
"[0,""newline""]","false",null
"[1,""x""]","1",false
"[1,""x""]","false",null
"[1]","false",null