0

好吧,我提前警告你,我对正则表达式的理解非常有限(这些年来我一直在努力学习它们,但说实话,我觉得它们只是吓到我了。)

假设我有以下字符串:

string keyValues = "CustomerId=1||OrderId=12||UserId=a1dcd568-f129-419b-b51e-be2dbb67de0f"

该字符串表示键值对,由用户定义的字符串(在本例中为||)(例如key1=value1||key2=value2)分隔。我试图从这个字符串中提取键并将它们存储在一个数组中。该数组如下所示:

{"CustomerId", "OrderId", "UserId"}

我能想到的最佳选择是使用正则表达式(如果有人有更好的解决方案,请分享)。这是我正在尝试做的事情:

string delimiter = "||";
string[] keys = Regex.Split(keyValues, "=.*" + delimiter);

我可能错了,但按照我的理解,正则表达式应该找到一个以 开头=和结尾的字符串,delimiter中间有任意数量的任何字符。这会在这些位置拆分字符串,留下原始键,但是,我的键数组看起来像这样:

{"", "C", "u", "s", "t", "o", "m", "e", "r", "I", "d", "", "", ...}

如您所见,该=value||部分已被剥离。谁能告诉我我做错了什么?

编辑

就我而言,分隔符||是一个变量。我没有提到这一点只是因为我认为我可以用 替换任何||引用delimiter。从给出的大多数答案中,我现在看到这是一个重要的细节。

4

4 回答 4

3

|在正则表达式中具有特殊含义(patA|patB匹配一个patAor patB)。逃脱|

使用非贪婪匹配 ( .*?):

string delimiter = "||";
string[] keys = Regex.Split(keyValues, @"=.*?" + Regex.Escape(delimiter));

这会给你{"CustomerId", "OrderId", "UserId=a1dcd568-f129-419b-b51e-be2dbb67de0f"}

Matches使用前瞻断言更合适:

string delimiter = "||";
string keyValues = "CustomerId=1||OrderId=12||UserId=a1dcd568-f129-419b-b51e-be2dbb67de0f";
string pattern = @"(?<=^|" + Regex.Escape(delimiter) + @")\w+(?==)";
var keys = Regex.Matches(keyValues, pattern);

@"verbatim string literal"顺便说一句,在表达正则表达式时使用逐字字符串文字 ( )。

演示

于 2013-10-29T15:36:15.800 回答
2

如果您只关心键,为什么不尝试使用匹配而不是使用拆分:

@"[^=|]+(?==)"

如果键不能包含等号=或竖线|,则上述表达式将匹配一个或多个不包含等号或后跟等号的字符=|从而=匹配键。

在 C# 中:

var input = "CustomerId=1||OrderId=12||UserId=a1dcd568-f129-419b-b51e-be2dbb67de0f";
var results = Regex.Matches(input, @"[^=|]+(?==)");
于 2013-10-29T15:39:30.243 回答
1

另一种方法是在没有正则表达式的情况下执行此操作,因为字符串操作非常基本:

string[] keys =
  keyValues.Split(new string[]{"||"}, StringSplitOptions.None)
  .Select(s => s.Substring(0, s.IndexOf('='))).ToArray();

将正则表达式保留为高级字符串操作。:)

(与使用正则表达式相比,测试此解决方案的性能时,显示速度快了大约 40 倍。)

于 2013-10-29T15:46:21.150 回答
0

拆分@"=[^|]*(?:\|\||$)"
如果您需要更多保证,请使用@"=[^=|]*(?:\|\||$)"

编辑为消耗不存在分隔符的末端。
如果在 C# 中,请尝试仅使用无空白元素。

于 2013-10-29T15:44:58.370 回答