【问题标题】:Split a string by semicolons while accounting for escaped characters用分号拆分字符串,同时考虑转义字符
【发布时间】:2009-07-03 11:25:36
【问题描述】:

很简单的问题:

我想将一个连接字符串拆分成它的关键字/值对,例如下面的连接字符串:

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 documentation 声明如果连接字符串值包含在单引号或双引号字符中,则允许包含分号,(因此,如果我理解以下内容将是有效的):

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

分割这个字符串的最佳方法是什么(在 C# 中)?

【问题讨论】:

    标签: c# string connection-string


    【解决方案1】:

    有一个 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】:

    你应该实现某种简单的字符串解析 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);
    }
    

    【讨论】:

      【解决方案3】:

      您可以编写一个迷你解析器。在跟踪引用状态的字符串中移动。一般情况下可能更可靠。

      另一种选择是使用正则表达式,并匹配整个内容,可以在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);
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        如果是 SQL Server,您可以简单地做:

        SqlConnectionStringBuilder decoder = new SqlConnectionStringBuilder(connectionString);
        
        string UserID = decoder.UserID; 
        string Password = decoder.Password; 
        

        等等

        【讨论】:

          猜你喜欢
          • 2013-02-17
          • 2021-01-19
          • 2020-10-14
          • 1970-01-01
          • 1970-01-01
          • 2013-05-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多