在考虑转义字符时,用分号拆分字符串

时间:2022-08-22 12:59:55

Really simple problem:

真的很简单的问题:

I want to split a connection string into its keyword / value pairs, so for example the following connection string:

我想将连接字符串拆分为其关键字/值对,例如以下连接字符串:

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

Would become:

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

The trouble is that the MSDN documentation states that connection string values are allowed to contain semicolons if the value is enclosed in single or double quote characters, (so if I understand it the following would be valid):

问题是MSDN文档声明如果值包含在单引号或双引号字符中,则允许连接字符串值包含分号(因此,如果我理解,则以下内容有效):

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

Whats the best way of splitting this string (in C#)?

什么是拆分此字符串的最佳方式(在C#中)?

4 个解决方案

#1


There is a DBConnectionStringBuilder class that will do what you want...

有一个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]));
        }

#2


You should implement some sort of simple string parsing respecing quotes. Something like that:

您应该实现某种简单的字符串解析重新引用。像这样的东西:

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);
}

#3


You can write a mini-parser. Moves through the string keeping track of the quoting state. Likely more reliable in general.

你可以写一个迷你解析器。移动字符串以跟踪引用状态。一般来说可能更可靠。

The other option is to use a regular expression, and match the whole content, which can be captured in a regex.Split rather than skipping the output:

另一个选项是使用正则表达式,并匹配整个内容,可以在regex.Split中捕获而不是跳过输出:

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

This assumes:

  • No ability to quote quotes inside quotes (or otherwise)
  • 无法在引号内引用引号(或其他方式)

  • Content on names is limited to white space and alpha-numerics (replace [\s\w] with group that covers valid characters).
  • 名称上的内容仅限于空格和字母数字(将[\ s \ w]替换为覆盖有效字符的组)。

Personally if I couldn't workout the regex quite quickly I'd go with the parser.

就个人而言,如果我不能很快地锻炼正则表达式,我会选择解析器。

EDIT: There is an easier way. DbConnectionStringBuilder implements IEnumerable, so get it to do the work:

编辑:有一个更简单的方法。 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);
        }
    }
}

#4


In case of SQL Server you can do simply:

对于SQL Server,您可以简单地执行以下操作:

SqlConnectionStringBuilder decoder = new SqlConnectionStringBuilder(connectionString);

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

etc.

#1


There is a DBConnectionStringBuilder class that will do what you want...

有一个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]));
        }

#2


You should implement some sort of simple string parsing respecing quotes. Something like that:

您应该实现某种简单的字符串解析重新引用。像这样的东西:

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);
}

#3


You can write a mini-parser. Moves through the string keeping track of the quoting state. Likely more reliable in general.

你可以写一个迷你解析器。移动字符串以跟踪引用状态。一般来说可能更可靠。

The other option is to use a regular expression, and match the whole content, which can be captured in a regex.Split rather than skipping the output:

另一个选项是使用正则表达式,并匹配整个内容,可以在regex.Split中捕获而不是跳过输出:

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

This assumes:

  • No ability to quote quotes inside quotes (or otherwise)
  • 无法在引号内引用引号(或其他方式)

  • Content on names is limited to white space and alpha-numerics (replace [\s\w] with group that covers valid characters).
  • 名称上的内容仅限于空格和字母数字(将[\ s \ w]替换为覆盖有效字符的组)。

Personally if I couldn't workout the regex quite quickly I'd go with the parser.

就个人而言,如果我不能很快地锻炼正则表达式,我会选择解析器。

EDIT: There is an easier way. DbConnectionStringBuilder implements IEnumerable, so get it to do the work:

编辑:有一个更简单的方法。 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);
        }
    }
}

#4


In case of SQL Server you can do simply:

对于SQL Server,您可以简单地执行以下操作:

SqlConnectionStringBuilder decoder = new SqlConnectionStringBuilder(connectionString);

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

etc.