エスケープ文字を考慮して文字列をセミコロンで分割する
-
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);
}
ミニパーサーを作成できます。引用符の状態を追跡しながら文字列内を移動します。一般的には信頼性が高くなる可能性があります。
もう 1 つのオプションは、正規表現を使用して、コンテンツ全体と一致させることです。 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;
など。
所属していません StackOverflow