Jquery-csv प्लग-इन में CSV पार्सर का उपयोग किया जाता है
यह एक बुनियादी चॉम्स्की टाइप III व्याकरण पार्सर है।
एक regex टोकन का उपयोग चार-चार-चार आधार पर डेटा का मूल्यांकन करने के लिए किया जाता है। जब एक नियंत्रण चार का सामना करना पड़ता है, तो कोड को प्रारंभिक स्थिति के आधार पर आगे के मूल्यांकन के लिए एक स्विच स्टेटमेंट में पास किया जाता है। गैर-नियंत्रण वर्णों को समूहीकृत और कॉपी किया जाता है, जिन्हें स्ट्रिंग कॉपी संचालन की संख्या को कम करने की आवश्यकता होती है।
टोकनधारक:
var tokenizer = /("|,|\n|\r|[^",\r\n]+)/;
मैचों का पहला सेट नियंत्रण वर्ण हैं: मूल्य सीमांकक (") मूल्य विभाजक (,) और प्रविष्टि विभाजक (नईलाइन के सभी रूपांतर)। अंतिम मैच गैर-नियंत्रण चार समूहीकरण को संभालता है।
पार्सर को संतुष्ट करने के 10 नियम हैं:
- नियम # 1 - प्रति पंक्ति एक प्रविष्टि, प्रत्येक पंक्ति एक नई रेखा के साथ समाप्त होती है
- नियम # 2 - फ़ाइल के अंत में अनुगामी नईलाइन छोड़ी गई
- नियम # 3 - पहली पंक्ति में हेडर डेटा होता है
- नियम # 4 - रिक्त स्थान को डेटा माना जाता है और प्रविष्टियों में अनुगामी अल्पविराम नहीं होना चाहिए
- नियम # 5 - डबल-कोट्स द्वारा लाइनों को सीमांकित किया जा सकता है या नहीं किया जा सकता है
- नियम # 6 - लाइन-ब्रेक, डबल-कोट्स और कॉमा से युक्त फ़ील्ड्स को डबल-कोट्स में संलग्न किया जाना चाहिए
- नियम # 7 - यदि डबल-कोट्स का उपयोग खेतों को घेरने के लिए किया जाता है, तो एक मैदान के अंदर दिखने वाले दोहरे-उद्धरण को दूसरे दोहरे उद्धरण के साथ पूर्ववर्ती होने से बचना चाहिए
- संशोधन # 1 - एक निर्विवाद क्षेत्र या हो सकता है
- संशोधन # 2 - एक उद्धृत क्षेत्र हो सकता है या नहीं
- संशोधन # 3 - प्रविष्टि में अंतिम फ़ील्ड में शून्य मान हो सकता है या नहीं भी हो सकता है
नोट: शीर्ष 7 नियम IETF RFC 4180 से सीधे प्राप्त होते हैं । अंतिम 3 को आधुनिक स्प्रेडशीट ऐप्स (एक्सेल, Google स्प्रैडशीट) द्वारा पेश किए गए किनारे के मामलों को कवर करने के लिए जोड़ा गया था जो डिफ़ॉल्ट रूप से सभी मानों को सीमांकित (यानी उद्धरण) नहीं करते हैं। मैंने RFC में परिवर्तनों को वापस करने में योगदान करने की कोशिश की, लेकिन अभी तक मेरी जांच का जवाब नहीं मिला है।
हवा के साथ पर्याप्त, यहाँ आरेख है:
राज्य अमेरिका:
- एक प्रविष्टि और / या एक मूल्य के लिए प्रारंभिक स्थिति
- एक शुरुआती उद्धरण का सामना किया गया है
- एक दूसरे उद्धरण का सामना किया गया है
- एक गैर-उद्धृत मूल्य का सामना किया गया है
संक्रमण:
- ए। दोनों उद्धृत मूल्यों (1), निर्विवाद मान (3), अशक्त मान (0), अशक्त प्रविष्टियाँ (0), और नई प्रविष्टियाँ (0)
- ख। एक दूसरे उद्धरण चार के लिए जाँच (2)
- सी। एक बची हुई बोली (1), मूल्य का अंत (0), और प्रविष्टि का अंत (0)
- घ। मान का अंत (0), और प्रविष्टि का अंत (0)
नोट: यह वास्तव में एक राज्य को याद कर रहा है। राज्य '1' से चिह्नित 'c' -> 'b' से एक रेखा होनी चाहिए क्योंकि एक बचा हुआ दूसरा सीमांकक का मतलब है कि पहला सीमांकक अभी भी खुला है। वास्तव में, संभवतः इसे एक और संक्रमण के रूप में प्रतिनिधित्व करना बेहतर होगा। इन्हें बनाना एक कला है, इसका कोई एक सही तरीका नहीं है।
नोट: यह एक निकास राज्य भी याद कर रहा है, लेकिन वैध डेटा पर पार्सर हमेशा संक्रमण 'ए' पर समाप्त होता है और राज्यों में से कोई भी संभव नहीं है क्योंकि पार्स के लिए कुछ भी नहीं बचा है।
राज्यों और परिवर्तनों के बीच का अंतर:
एक अवस्था परिमित है, जिसका अर्थ है कि केवल एक बात का अनुमान लगाया जा सकता है।
एक संक्रमण राज्यों के बीच प्रवाह का प्रतिनिधित्व करता है तो इसका मतलब कई चीजें हो सकती हैं।
मूल रूप से, राज्य-> संक्रमण संबंध 1 -> * है (यानी एक-से-कई)। राज्य 'यह क्या है' को परिभाषित करता है और संक्रमण 'यह कैसे संभाला जाता है' को परिभाषित करता है।
नोट: चिंता मत करो अगर राज्यों / बदलावों का अनुप्रयोग सहज महसूस नहीं करता है, तो यह सहज नहीं है। इससे पहले कि मैं आखिरकार इस अवधारणा को थामने के लिए किसी से अधिक होशियार हो गया, किसी और के साथ हो गया।
छद्म संहिता:
csv = // csv input string
// init all state & data
state = 0
value = ""
entry = []
output = []
endOfValue() {
entry.push(value)
value = ""
}
endOfEntry() {
endOfValue()
output.push(entry)
entry = []
}
tokenizer = /("|,|\n|\r|[^",\r\n]+)/gm
// using the match extension of string.replace. string.exec can also be used in a similar manner
csv.replace(tokenizer, function (match) {
switch(state) {
case 0:
if(opening delimiter)
state = 1
break
if(new-line)
endOfEntry()
state = 0
break
if(un-delimited data)
value += match
state = 3
break
case 1:
if(second delimiter encountered)
state = 2
break
if(non-control char data)
value += match
state = 1
break
case 2:
if(escaped delimiter)
state = 1
break
if(separator)
endOfValue()
state = 0
break
if(newline)
endOfEntry()
state = 0
break
case 3:
if(separator)
endOfValue()
state = 0
break
if(newline)
endOfEntry()
state = 0
break
}
}
नोट: यह सार है, व्यवहार में विचार करने के लिए और भी बहुत कुछ है। उदाहरण के लिए, त्रुटि की जाँच, शून्य मान, एक अनुगामी रिक्त रेखा (अर्थात जो मान्य है), आदि।
इस मामले में, राज्य चीजों की स्थिति है जब रेगेक्स मैच ब्लॉक एक पुनरावृत्ति को पूरा करता है। संक्रमण को स्टेटमेंट स्टेटमेंट के रूप में दर्शाया गया है।
मनुष्य के रूप में, हम उच्च स्तर सार लेकिन एक FSM के साथ काम करने में निम्न स्तर के संचालन को सरल बनाने की प्रवृति होती है निम्न स्तर के संचालन के साथ काम। जबकि राज्यों और संक्रमणों को व्यक्तिगत रूप से काम करना बहुत आसान है, एक बार में पूरे पूरे कल्पना करना स्वाभाविक है। मुझे यह पता चला कि जब तक संक्रमण बाहर न खेले, मैं अंत तक बार-बार निष्पादन के अलग-अलग रास्तों का पालन करना आसान समझता हूं। यह बुनियादी गणित सीखने की तरह है, आप उच्च स्तर से कोड का मूल्यांकन करने में सक्षम नहीं होंगे जब तक कि निम्न स्तर का विवरण स्वचालित नहीं हो जाता।
एक तरफ: यदि आप वास्तविक कार्यान्वयन को देखते हैं, तो बहुत सारे विवरण गायब हैं। सबसे पहले, सभी असंभव पथ विशिष्ट अपवादों को फेंक देंगे। उन्हें हिट करना असंभव होना चाहिए, लेकिन अगर कुछ भी टूटता है तो वे टेस्ट रनर में अपवाद को ट्रिगर करेंगे। दूसरा, 'कानूनी' CSV डेटा स्ट्रिंग में जो अनुमति दी जाती है, उसके लिए पार्सर नियम बहुत ढीले होते हैं, इसलिए बहुत सारे विशिष्ट किनारे मामलों को संभालने के लिए आवश्यक कोड। उस तथ्य के बावजूद, यह एफएसएम को बग फिक्स, एक्सटेंशन और फाइन ट्यूनिंग के सभी से पहले मॉक करने की प्रक्रिया थी।
अधिकांश डिजाइनों के साथ, यह कार्यान्वयन का सटीक प्रतिनिधित्व नहीं है, लेकिन यह महत्वपूर्ण भागों को रेखांकित करता है। व्यवहार में, वास्तव में इस डिज़ाइन से प्राप्त 3 अलग-अलग पार्सर फ़ंक्शन हैं: एक सीएसवी-विशिष्ट लाइन स्प्लिटर, एक सिंगल-लाइन पार्सर और एक पूर्ण मल्टी-लाइन पार्सर। वे सभी समान तरीके से काम करते हैं, वे जिस तरह से न्यूलाइन चार्ट को संभालते हैं, उसमें भिन्नता है।