2016-01-05 3 views
7

अगर मैं एक string इसपार्स स्ट्रिंग (उद्धरण चिह्न के साथ बनाए रखा)

create myclass "56, 'for the better or worse', 54.781" 

की तरह मैं इसे कैसे इस तरह के परिणाम तीन स्ट्रिंग "शब्द" है जो हो सकता है कि पार्स कर सकते है निम्नलिखित सामग्री:

[0] create 
[1] myclass 
[2] "56, 'for the better or worse', 54.781" 

संपादित करें 2: ध्यान दें कि उद्धरण चिह्नों

बनाए रखे जाने की कर रहे हैं सबसे पहले, मैं string.Split(' ') का उपयोग करके प्रयास किया, लेकिन मैंने देखा कि यह तीसरे string को कुछ अन्य तारों से तोड़ देगा।

मैं इसे हल करने के लिए count तर्क 3 के उपयोग से Split परिणाम को सीमित करने का प्रयास करता हूं। और यह इस मामले के लिए ठीक है, लेकिन जब दिए गए स्ट्रिंग

create myclass false "56, 'for the better or worse', 54.781" //or 
create myclass "56, 'for the better or worse', 54.781" false 

है तो स्प्लिट में विफल रहता है, क्योंकि पिछले दो शब्द जोड़ दिए जाएँगे।

मैं भी

यहाँ मेरी ReadInBetweenSameDepth विधि

//Examples: 
    //[1] (2 + 1) * (5 + 6) will return 2 + 1 
    //[2] (2 * (5 + 6) + 1) will return 2 * (5 + 6) + 1 
public static string ReadInBetweenSameDepth(string str, char delimiterStart, char delimiterEnd) { 
    if (delimiterStart == delimiterEnd || string.IsNullOrWhiteSpace(str) || str.Length <= 2) 
    return null; 
    int delimiterStartFound = 0; 
    int delimiterEndFound = 0; 
    int posStart = -1; 
    for (int i = 0; i < str.Length; ++i) { 
    if (str[i] == delimiterStart) { 
     if (i >= str.Length - 2) //delimiter start is found in any of the last two characters 
     return null; //it means, there isn't anything in between the two 
     if (delimiterStartFound == 0) //first time 
     posStart = i + 1; //assign the starting position only the first time... 
     delimiterStartFound++; //increase the number of delimiter start count to get the same depth 
    } 
    if (str[i] == delimiterEnd) { 
     delimiterEndFound++; 
     if (delimiterStartFound == delimiterEndFound && i - posStart > 0) 
     return str.Substring(posStart, i - posStart); //only successful if both delimiters are found in the same depth 
    } 
    } 
    return null; 
} 

है लेकिन हालांकि इस समारोह काम कर रहा है, मैं यह बहुत मुश्किल गठबंधन करने के लिए पाया उद्धरण चिह्न के बीच में string पाने के लिए ReadInBetweenSameDepth की तरह कुछ बनाया जैसा कि मैं चाहता हूं सही पार्सिंग बनाने के लिए string.Split के साथ परिणाम।

संपादित करें 2: मेरी गरीब समाधान में, मैं उद्धरण चिह्नों बाद में

पर फिर से जोड़ने की जरूरत है वहाँ यह करने के लिए किसी भी बेहतर तरीका है? अगर हम Regex का उपयोग करते हैं, तो हम यह कैसे करते हैं?

संपादित करें:

मैं ईमानदारी से अनजान हैं कि इस समस्या को सीएसवी स्वरूपित पाठ के रूप में एक ही तरीके से हल किया जा सकता हूँ। न तो मुझे पता था कि यह समस्या Regex द्वारा हल नहीं की गई है (इस प्रकार मैंने इसे इस तरह लेबल किया है)। उन लोगों के लिए मेरी ईमानदारी से माफी जो इसे डुप्लिकेट पोस्ट के रूप में देखते हैं।

संपादित करें 2:

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

उत्तर

2

Regex Demo

(\w+|"[^"]*") 

पहले कैप्चर समूह में मैचों प्राप्त करें।

  1. \w+: अक्षरांकीय अक्षर से मेल खाता है और एक या अधिक बार
  2. "[^"]*" को रेखांकित: रेगुलर एक्सप्रेशन
+0

धन्यवाद, मैंने 'रेगेक्स' का परीक्षण किया और यह अच्छी तरह से काम किया। स्पष्टीकरण की भी सराहना करें। – Ian

+0

धन्यवाद श्री तुषार, डेटा के साथ आगे काम करने के बाद, ऐसा लगता है कि आपका सबसे अच्छा समाधान है, स्पष्टीकरण somemore के साथ। यहां मेरी दूसरी पोस्ट है जो मुझे ऐसा सोचती है: http://stackoverflow.com/questions/34624536/stringsplitoptions-removeemptyentries-equivalent-for-textfieldparser – Ian

3

आप इस

\s(?=(?:[^"]*"[^"]*")*[^"]*$) 

डेमो देखें द्वारा विभाजित कर सकते हैं।

https://regex101.com/r/fM9lY3/60

string strRegex = @"\s(?=(?:[^""]*""[^""]*"")*[^""]*$)"; 
Regex myRegex = new Regex(strRegex, RegexOptions.Multiline); 
string strTargetString = @"create myclass ""56, 'for the better or worse', 54.781"""; 

return myRegex.Split(strTargetString); 
+0

धन्यवाद, मुझे लगता है कि यह सबसे अच्छा जवाब है क्योंकि मैं कार्य के लिए सी # का उपयोग कर रहा हूं। मैं ईमानदारी से नहीं जानता कि मेरी समस्या सीएसवी पार्सिंग के समान ही है। – Ian

+1

ओह, चलो, यह सबसे बुरा जवाब है! ** यदि आप इसके बिना कर सकते हैं तो इस रेगेक्स का उपयोग न करें! ** देखें कि इसमें कितना बैकट्रैक शामिल है। मैं अधिक स्पष्टीकरण के साथ एक जवाब चुनना चाहता हूं। –

+0

@stribizhev क्या आपके पास बेहतर जवाब है, महोदय? चूंकि मेरी अपनी विधि सभी दिए गए उत्तरों की तुलना में स्पष्ट रूप से बदतर है। – Ian

1

मैं कोई वास्तविक प्रयोग करेंगे में OR शर्त: कुछ भी है कि दोहरे उद्धरण चिह्नों

  • | में लपेटा जाता है मेल इस कार्य के लिए सीएसवी-पार्सर। केवल एक ही ढांचे में उपलब्ध VisualBasic नाम स्थान में TextFieldParser-class है:

    string str = "create myclass \"56, 'for the better or worse', 54.781\""; 
    var allLineFields = new List<string[]>(); 
    using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(new StringReader(str))) 
    { 
        parser.Delimiters = new string[] { " " }; 
        parser.HasFieldsEnclosedInQuotes = true; // important 
        string[] lineFields; 
        while ((lineFields = parser.ReadFields()) != null) 
        { 
         allLineFields.Add(lineFields); 
        } 
    } 
    

    परिणाम:

    enter image description here

    लेकिन वहाँ दूसरों की तरह उपलब्ध this या this हैं।

  • +0

    धन्यवाद, मुझे नहीं पता था कि वीबी लाइब्रेरी में 'TextFieldParser' है जो कर सकता है इस तरह इस्तेमाल किया जाना चाहिए। मैं आपके इनपुट की सराहना करता हूं। +10 – Ian

    +0

    @ इयान: आप बिना किसी समस्या के सी # के साथ इसका उपयोग कर सकते हैं। यदि आप वास्तव में एक बड़ा टेक्स्ट पार्स कर रहे हैं तो यह रेगेक्स का उपयोग करने से अधिक कुशल है। आपका स्वागत है –

    +0

    ओ, मैं देखता हूं ... मेरा बुरा। जाहिर है, चूंकि इसे 'dll' में परिवर्तित किया गया है, तो यह' VB' की बजाय '.Net' वर्ग होना चाहिए जिसे इसे सी # में भी आसानी से उपयोग किया जा सकता है। सुधारों के लिए धन्यवाद। मैं इसके प्रदर्शन को भी देखूंगा। – Ian

    संबंधित मुद्दे