string emailBody = " holla holla testing is for NewFinancial History:\"xyz\" dsd NewFinancial History:\"abc\" NewEBTDI$:\"abc\" dsds ";
emailBody = string.Join(" ", Regex.Split(emailBody.Trim(), @"(?:\r\n|\n|\r)"));
var keys = Regex.Matches(emailBody, @"\bNew\B(.+?):", RegexOptions.Singleline).OfType<Match>().Select(m => m.Groups[0].Value.Replace(":", "")).Distinct().ToArray();
foreach (string key in keys)
{
List<string> valueList = new List<string>();
string regex = "" + key + ":" + "\"(?<" + GetCleanKey(key) + ">[^\"]*)\"";
var matches = Regex.Matches(emailBody, regex, RegexOptions.Singleline);
foreach (Match match in matches)
{
if (match.Success)
{
string value = match.Groups[GetCleanKey(key)].Value;
if (!valueList.Contains(value.Trim()))
{
valueList.Add(value.Trim());
}
}
}
public string GetCleanKey(string key)
{
return key.Replace(" ", "").Replace("-", "").Replace("#", "").Replace("$", "").Replace("*", "").Replace("!", "").Replace("@", "")
.Replace("%", "").Replace("^", "").Replace("&", "").Replace("(", "").Replace(")", "").Replace("[", "").Replace("]", "").Replace("?", "")
.Replace("<", "").Replace(">", "").Replace("'", "").Replace(";", "").Replace("/", "").Replace("\"", "").Replace("+", "").Replace("~", "").Replace("`", "")
.Replace("{", "").Replace("}", "").Replace("+", "").Replace("|", "");
}
在我的上述代码中,我尝试获取NewEBTDI$:
旁边的值"abc"
。
当我在模式中包含$
符号时,它不会搜索字段名称旁边的值。
如果$
被删除,而其中一个只是指定NewEBTDI
,那么它会搜索这些值。
我希望将值与$
符号一起搜索。
答案 0 :(得分:5)
处理正则表达式中具有特殊含义但必须按原样搜索的字符的正确方法是逃避它们。您可以使用Regex.Escape
执行此操作。在您的情况下,它是$
符号,这意味着正则表达式中行尾,如果没有转义。
string regex = "" + Regex.Escape(key) + ":" + "\"(?<" + Regex.Escape(GetCleanKey(key))
+ ">[^\"]*)\"";
或
string regex = String.Format("{0}:\"(?<{1}>[^\"]*)\"",
Regex.Escape(key),
Regex.Escape(GetCleanKey(key)));
或使用VS 2015,使用字符串插值:
string regex = $"{Regex.Escape(key)}:\"(?<{Regex.Escape(GetCleanKey(key))}>[^\"]*)\"";
(它看起来确实比实际情况更好,因为C#编辑器对字符串部分和嵌入式C#表达式进行了不同的着色。)
答案 1 :(得分:1)
目前还不清楚最终目标是什么,但模式中的$
是模式转义,这意味着行的结尾或缓冲区的结尾取决于是否设置了MultiLine
或不。
为什么不将:
之前的文本捕获到命名捕获中?然后提取引用的操作值,例如:
var data = "...is for NewFinancial History:\"xyz\" dsd NewFinancial History:\"abc\" NewEBTDI$:\"abc\" dsds";
var pattern = @"
(?<New>New[^:]+) # Capture all items after `New` that is *not* (`^`) a `:`, one or more.
: # actual `:`
\x22 # actual quote character begin anchor
(?<InQuotes>[^\x22]+) # text that is not a quote, one or more
\x22 # actual quote ending anchor
";
// IgnorePatternWhitespace allows us to comment the pattern. Does not affect processing.
Regex.Matches(data, pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture)
.OfType<Match>()
.Select(mt => new
{
NewText = mt.Groups["New"].Value,
Text = mt.Groups["InQuotes"].Value
});
<强>结果强>
注意我使用十字转义\x22
而不是转义模式中的\"
以便于使用它。因为它绕过C#编译器过早地转义需要保持原样的模式转义。