[英]What is the best way to parse this string in C#?
我有一個從另一個系統讀取的字符串。 它基本上是一個長字符串,表示一個鍵值對列表,它們之間用空格分隔。 它看起來像這樣:
key:value[space]key:value[space]key:value[space]
所以我寫了這段代碼來解析它:
string myString = ReadinString();
string[] tokens = myString.split(' ');
foreach (string token in tokens) {
string key = token.split(':')[0];
string value = token.split(':')[1];
. . . .
}
現在的問題是某些值中有空格,因此我在頂部的“簡單”拆分不再有效。 我想看看我如何仍然可以解析出鍵值對列表(給定空格作為分隔符),因為我知道值字段中也可能有空格,因為 split 似乎無法做到工作了。
注意:我現在確認鍵中不會有空格,所以我只需要擔心值。 為混亂道歉。
使用這個正則表達式:
\w+:[\w\s]+(?![\w+:])
我在上面測試過
test:testvalue test2:test value test3:testvalue3
它返回三個匹配項:
test:testvalue
test2:test value
test3:testvalue3
您可以將\w
更改為輸入中可能出現的任何字符集。
用於測試的代碼:
var regex = new Regex(@"\w+:[\w\s]+(?![\w+:])");
var test = "test:testvalue test2:test value test3:testvalue3";
foreach (Match match in regex.Matches(test))
{
var key = match.Value.Split(':')[0];
var value = match.Value.Split(':')[1];
Console.WriteLine("{0}:{1}", key, value);
}
Console.ReadLine();
正如 Wonko the Sane 指出的那樣,這個正則表達式將在帶有:
的值上失敗。 如果您預測這種情況,請使用\w+:[\w: ]+?(?:[\w+:])
作為正則表達式。 但是,當value
中的冒號前面有空格時,這仍然會失敗......我會考慮解決這個問題。
如果不將拆分從空格更改為“|”等其他內容,這將無法工作。
考慮一下:
阿爾弗雷德·貝斯特:阿爾弗雷德·貝斯特 阿爾弗雷德·阿爾弗雷德·貝斯特
string input = "foo:Foobarius Maximus Tiberius Kirk bar:Barforama zap:Zip Brannigan";
foreach (Match match in Regex.Matches(input, @"(\w+):([^:]+)(?![\w+:])"))
{
Console.WriteLine("{0} = {1}",
match.Groups[1].Value,
match.Groups[2].Value
);
}
給你:
foo = Foobarius Maximus Tiberius Kirk
bar = Barforama
zap = Zip Brannigan
您可以嘗試 Url 對空格之間的內容進行編碼(鍵和值不是:符號),但這需要您控制輸入法。
或者您可以簡單地使用另一種格式(如 XML 或 JSON),但您需要再次控制輸入格式。
如果您無法控制輸入格式,您始終可以使用正則表達式並搜索單詞 plus: 后面的單個空格。
更新(感謝 Jon Grant)看來您可以在鍵和值中有空格。 如果是這種情況,您將需要認真重新考慮您的策略,因為即使正則表達式也無濟於事。
string input = "key1:value key2:value key3:value";
Dictionary<string, string> dic = input.Split(' ').Select(x => x.Split(':')).ToDictionary(x => x[0], x => x[1]);
第一個將產生一個數組:
"key:value", "key:value"
然后是arrays的數組:
{ "key", "value" }, { "key", "value" }
然后是字典:
"key" => "value", "key" => "value"
請注意, Dictionary<K,V>
不允許重復鍵,在這種情況下會引發異常。 如果可能出現這種情況,請使用ToLookup()
。
使用正則表達式可以解決您的問題:
private void DoSplit(string str)
{
str += str.Trim() + " ";
string patterns = @"\w+:([\w+\s*])+[^!\w+:]";
var r = new System.Text.RegularExpressions.Regex(patterns);
var ms = r.Matches(str);
foreach (System.Text.RegularExpressions.Match item in ms)
{
string[] s = item.Value.Split(new char[] { ':' });
//Do something
}
}
我想你可以采用你的方法並稍微擴展它來處理這些東西......
偽代碼種類:
List<string> parsedTokens = new List<String>();
string[] tokens = myString.split(' ');
for(int i = 0; i < tokens.Length; i++)
{
// We need to deal with the special case of the last item,
// or if the following item does not contain a colon.
if(i == tokens.Length - 1 || tokens[i+1].IndexOf(':' > -1)
{
parsedTokens.Add(tokens[i]);
}
else
{
// This bit needs to be refined to deal with values with multiple spaces...
parsedTokens.Add(tokens[i] + " " + tokens[i+1]);
}
}
另一種方法是在冒號上拆分......這樣,您的第一個數組項將是第一個鍵的名稱,第二個項目將是第一個鍵的值,然后是第二個鍵的名稱(可以使用 LastIndexOf分開),等等。 如果值可以包含冒號,或者鍵可以包含空格,這顯然會變得非常混亂,但在這種情況下,你會很不走運......
此代碼將執行此操作(鑒於以下規則)。 它解析鍵和值並以Dictonary<string, string>
數據結構返回它們。 我在最后添加了一些代碼,假設給定您的示例,整個字符串/流的最后一個值將附加一個 [空格]:
private Dictionary<string, string> ParseKeyValues(string input)
{
Dictionary<string, string> items = new Dictionary<string, string>();
string[] parts = input.Split(':');
string key = parts[0];
string value;
int currentIndex = 1;
while (currentIndex < parts.Length-1)
{
int indexOfLastSpace=parts[currentIndex].LastIndexOf(' ');
value = parts[currentIndex].Substring(0, indexOfLastSpace);
items.Add(key, value);
key = parts[currentIndex].Substring(indexOfLastSpace + 1);
currentIndex++;
}
value = parts[parts.Length - 1].Substring(0,parts[parts.Length - 1].Length-1);
items.Add(key, parts[parts.Length-1]);
return items;
}
注意:此算法假定以下規則:
沒有任何正則表達式或字符串連接,並且作為可枚舉(它假設鍵沒有空格,但值可以):
public static IEnumerable<KeyValuePair<string, string>> Split(string text)
{
if (text == null)
yield break;
int keyStart = 0;
int keyEnd = -1;
int lastSpace = -1;
for(int i = 0; i < text.Length; i++)
{
if (text[i] == ' ')
{
lastSpace = i;
continue;
}
if (text[i] == ':')
{
if (lastSpace >= 0)
{
yield return new KeyValuePair<string, string>(text.Substring(keyStart, keyEnd - keyStart), text.Substring(keyEnd + 1, lastSpace - keyEnd - 1));
keyStart = lastSpace + 1;
}
keyEnd = i;
continue;
}
}
if (keyEnd >= 0)
yield return new KeyValuePair<string, string>(text.Substring(keyStart, keyEnd - keyStart), text.Substring(keyEnd + 1));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.