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

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

  •  21-08-2019
  •  | 
  •  

سؤال

مشكلة بسيطة حقا:

أرغب في تقسيم سلسلة اتصال إلى أزواج الكلمات الرئيسية/القيم الخاصة بها، على سبيل المثال سلسلة الاتصال التالية:

Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=vm-jp-dev2;Data Source=scsql\sql2005;Auto Translate=False

قد يصبح:

Provider=SQLOLEDB.1
Integrated Security=SSPI
Persist Security Info=False
Initial Catalog=vm-jp-dev2
Data Source=scsql\sql2005
Auto Translate=False

والمشكلة هي أن وثائق MSDN تنص على أنه يُسمح لقيم سلسلة الاتصال أن تحتوي على فواصل منقوطة إذا كانت القيمة محاطة بأحرف اقتباس مفردة أو مزدوجة، (لذلك إذا فهمت ذلك فسيكون ما يلي صالحًا):

Provider="Some;Provider";Initial Catalog='Some;Catalog';...

ما هي أفضل طريقة لتقسيم هذه السلسلة (في C#)؟

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

المحلول

وهناك فئة DBConnectionStringBuilder من شأنها أن تفعل ما تريد ...

        System.Data.Common.DbConnectionStringBuilder builder = new System.Data.Common.DbConnectionStringBuilder();

        builder.ConnectionString = "Provider=\"Some;Provider\";Initial Catalog='Some;Catalog';";

        foreach (string key in builder.Keys)
        {
            Response.Write(String.Format("{0}: {1}<br>", key , builder[key]));
        }

نصائح أخرى

ويجب تنفيذ نوعا من سلسلة بسيطة تحليل نقلت respecing. شيء من هذا القبيل:

public static IEnumerable<string> SplitString(string str)
{
    int StartIndex = 0;
    bool IsQuoted = false;
    for (int I = 0; I < str.Length; I++)
    {
        if (str[I] == '"')
            IsQuoted = !IsQuoted;
        if ((str[I] == ';') && !IsQuoted)
        {
            yield return str.Substring(StartIndex, I - StartIndex);        
            StartIndex = I + 1;
        }
    }

    if (StartIndex < str.Length)
        yield return str.Substring(StartIndex);
}

يمكنك كتابة محلل صغير.يتحرك عبر السلسلة لتتبع حالة الاقتباس.من المحتمل أن يكون أكثر موثوقية بشكل عام.

الخيار الآخر هو استخدام تعبير عادي، ومطابقة المحتوى بالكامل، والذي يمكن التقاطه في ملف regex.Split بدلاً من تخطي الإخراج:

var re = new Regex(@"([\w\s]+=\s*?(?:['""][\w\s]+['""]|[\w\s]+));");
var parts = re.Split(connectionString)

هذا يفترض:

  • لا توجد القدرة على اقتباس علامات الاقتباس داخل علامات الاقتباس (أو غير ذلك)
  • يقتصر محتوى الأسماء على المسافة البيضاء والأحرف الرقمية (استبدل [\s\w] بمجموعة تغطي الأحرف الصالحة).

شخصيًا، إذا لم أتمكن من تمرين التعبير العادي بسرعة كبيرة، فسأختار المحلل اللغوي.

يحرر:هناك طريقة أسهل. DbConnectionStringBuilder ينفذ IEnumerable, ، لذا احصل عليه للقيام بهذا العمل:

using System;
using System.Collections.Generic;
using System.Data.Common;

class Program {
    static void Main(string[] args) {
        string conStr = @"Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=vm-jp-dev2;Data Source='scsql\sql;2005';Auto Translate=False";

        var cb = new DbConnectionStringBuilder();
        cb.ConnectionString = conStr;
        int n = 0;
        foreach (KeyValuePair<string, object> c in cb) {
            Console.WriteLine("#{0}: {1}={2}", ++n, c.Key, c.Value);
        }
    }
}

في حالة من SQL Server يمكن أن تفعل ببساطة:

SqlConnectionStringBuilder decoder = new SqlConnectionStringBuilder(connectionString);

string UserID = decoder.UserID; 
string Password = decoder.Password; 

وغيرها.

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