تبحث عن Regex أن تجد نقلت أسطر في سلسلة الكبيرة (C#)

StackOverflow https://stackoverflow.com/questions/33063

  •  09-06-2019
  •  | 
  •  

سؤال

لدي سلسلة (دعنا نسميها ملف CSV ، على الرغم من أنها ليست في الواقع واحدة, سيكون من السهل الآن) أن لدي تحليل في التعليمات البرمجية C#.
الخطوة الأولى من عملية تحليل يقسم الملف الى خطوط الفردية فقط باستخدام StreamReader موضوع الدعوة ReadLine حتى إنه من خلال الملف.ومع ذلك ، فإن أي خط معين قد تحتوي على علامات الاقتباس (في علامات الاقتباس المفردة) الحرفي مع جزءا لا يتجزأ من أسطر.كنت بحاجة إلى العثور على تلك الأسطر الجديدة وتحويلها مؤقتا إلى نوع آخر من رمزية أو تسلسل الهروب حتى لقد تقسيم الملف إلى مجموعة من الخطوط..ثم أنا يمكن تغييرها مرة أخرى.

على سبيل المثال إدخال البيانات:

1,2,10,99,'Some text without a newline', true, false, 90
2,1,11,98,'This text has an embedded newline 
                and continues here', true, true, 90

يمكنني أن أكتب كل من التعليمات البرمجية C# في حاجة إلى القيام بذلك عن طريق استخدام string.IndexOf أن تجد نقلت أقسام والبحث داخلها عن أسطر ، ولكن أنا أفكر Regex قد يكون خيارا أفضل (أي الآن لدي مشكلتين)

هل كانت مفيدة؟

المحلول

لأن هذا ليس صحيحا ملف CSV, أنها لا تملك أي نوع من التحكم.

من المثال الخاص بك يبدو عليك:int, int, int, int, string منطقي منطقي ، الباحث

مع أن يجعل السجل الخاص بك / الكائن.

على افتراض أن البيانات الخاصة بك بشكل جيد (أنا لا أعرف ما يكفي عن المصدر أن أعرف مدى صحة هذا الافتراض) ، هل يمكن أن:

  1. قراءة الخط الخاص بك.
  2. استخدام آلة الدولة لتحليل البيانات الخاصة بك.
  3. إذا كان لديك خط ينتهي وأنت تحليل سلسلة قراءة السطر التالي..والحفاظ على تحليل.

وأود أن تجنب باستخدام التعابير المنطقية إذا كان ذلك ممكنا.

نصائح أخرى

الدولة-آلات للقيام بمثل هذا العمل هي سهلة باستخدام C# 2.0 التكرار.وهنا نأمل آخر CSV محلل أكتبهاكل ملف يتم التعامل مع enumerable مجموعة من enumerable السلاسل ، أيالصفوف/الأعمدة.IEnumerable كبيرة لأنه يمكن بعد ذلك معالجتها من خلال LINQ المشغلين.

public class CsvParser
{
    public char FieldDelimiter { get; set; }

    public CsvParser()
        : this(',')
    {
    }

    public CsvParser(char fieldDelimiter)
    {
        FieldDelimiter = fieldDelimiter;
    }

    public IEnumerable<IEnumerable<string>> Parse(string text)
    {
        return Parse(new StringReader(text));
    }
    public IEnumerable<IEnumerable<string>> Parse(TextReader reader)
    {
        while (reader.Peek() != -1)
            yield return parseLine(reader);
    }

    IEnumerable<string> parseLine(TextReader reader)
    {
        bool insideQuotes = false;
        StringBuilder item = new StringBuilder();

        while (reader.Peek() != -1)
        {
            char ch = (char)reader.Read();
            char? nextCh = reader.Peek() > -1 ? (char)reader.Peek() : (char?)null;

            if (!insideQuotes && ch == FieldDelimiter)
            {
                yield return item.ToString();
                item.Length = 0;
            }
            else if (!insideQuotes && ch == '\r' && nextCh == '\n') //CRLF
            {
                reader.Read(); // skip LF
                break;
            }
            else if (!insideQuotes && ch == '\n') //LF for *nix-style line endings
                break;
            else if (ch == '"' && nextCh == '"') // escaped quotes ""
            {
                item.Append('"');
                reader.Read(); // skip next "
            }
            else if (ch == '"')
                insideQuotes = !insideQuotes;
            else
                item.Append(ch);
        }
        // last one
        yield return item.ToString();
    }

}

علما أن الملف هو قراءة حرف حرف مع رمز اتخاذ قرار عندما أسطر هي أن يعامل الصف المحددات أو جزء من سلسلة مقتبسة.

ما إذا كنت حصلت على الملف بأكمله إلى متغير ثم تقسيم ذلك على أساس غير ونقلت أسطر?

تحرير: اسف لقد أسأت فهم وظيفة الخاص بك.إذا كنت تبحث عن regex ، ثم هنا هو واحد:

content = Regex.Replace(content, "'([^']*)\n([^']*)'", "'\1TOKEN\2'");

قد يكون هناك الحالات حافة وأن اثنين من المشاكل ولكن أعتقد أنه يجب أن تكون على ما يرام في معظم الوقت.ما Regex يفعله هو أنه لأول مرة يجد أي زوج من علامات الاقتباس المفردة التي بينه و الاستعاضة عن ذلك مع رمز الحفاظ على أي نص في ما بينهما.

ولكن لا يزال كنت أذهب آلة الدولة مثل ما @bryansh هو موضح أدناه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top