我有这个巨大的RegEx用于匹配信用卡号码。但它的PCRE。在PHP中完美运行。
/(\d{13,16})(?(?=<)<|["']).*?(?=(?(?=>)>|["\'])\d{3,4}(?(?=<)<|["']))(?(?=>)>|["'])(\d{3,4})(?(?=<)<|["'])/is
// /i = ignore case
// /s = treat the subject as a single line
我将它转换为.NET。刚刚在开头添加@
并将双引号加倍。我认为这是正确的程序。
@"(\d{13,16})(?(?=<)<|[""]).*?(?=(?(?=>)>|[""])\d{3,4}(?(?=<)<|[""]))(?(?=>)>|[""])(\d{3,4})(?(?=<)<|[""])"
现在它不匹配。我知道PCRE和.NET实现可能不一样。但我认为我可以将其转换为兼容的。我查看MSDN reference。看来我的模式没有什么特别的可能是PCRE特有的。
在分析模式后,我发现(?(?=<)<|[""])
不匹配!因此使正则表达式更简单。它现在@"(?(?=q)qu|\w)\w+"
。我正在匹配"Queen, Quick, Qi etc"
$data = "Queen, Quick, Qi etc";
$pattern = "(?(?=q)qu|\w)\w+";
preg_match_all("/$pattern/is", $data, $matches);
print_r($matches);
Array
(
[0] => Array
(
[0] => Queen
[1] => Quick
[2] => etc
)
)
string data = "Queen, Quick, Qi etc";
string pattern = @"(?(?=q)qu|\w)\w+";
Regex re = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
foreach (Match m in re.Matches(data))
{
if (m.Success)
{
//Console.WriteLine("Credit Card Number={0}, CCV={1}", m.Groups[1].Value, m.Groups[6].Value);
for (int i = 1; i < m.Groups.Count; i++)
{
Console.WriteLine("[{0}][{1}]", i, m.Groups[i].Value);
for (int j = 0; j < m.Groups[i].Captures.Count; j++)
{
Console.WriteLine("[{0}][{1}][{2}]", i, m.Groups[i].Value, m.Groups[i].Captures[j].Value);
}
}
}
}
Press any key to continue . . .
输出无效。
我的问题是
@"(?(?=q)qu|\w)\w+"
,使其与.NET中的PHP匹配?由于
答案 0 :(得分:2)
1:条件语在.NET中工作就像在PHP中一样。
2:“更简单”的正则表达式对于.NET是正确的。你刚才错了:
你的正则表达式中没有捕获组。这意味着循环
for (int i = 1; i < m.Groups.Count; i++) {...}
永远不会被执行,因为m.Groups.Count
是1。
正确的方法是
foreach (Match m in re.Matches(data))
{
if (m.Success)
{
for (int i = 0; i < m.Groups.Count; i++) // Groups are numbered from zero
{
// Groups[0] is the entire match
Console.WriteLine("[{0}][{1}]", i, m.Groups[i].Value);
}
}
}
3:你的正则表达式缺少单引号。
Regex regexObj = new Regex(@"(\d{13,16})(?(?=<)<|[""']).*?(?=(?(?=>)>|[""'])\d{3,4}(?(?=<)<|[""']))(?(?=>)>|[""'])(\d{3,4})(?(?=<)<|[""'])", RegexOptions.Singleline);
将是字面翻译。
4。:您不需要/i
或Ignorecase
参数,因为正则表达式中没有字母。
5:(?(?=<)<|["'])
毫无意义。它与[<"']
完全匹配相同的文本。毕竟,这意味着“如果有<
,则匹配<
。否则,请尝试匹配"
或'
。无需使用有条件的正则表达式。
因此整个正则表达式可以简化为
(\d{13,16})[<"'].*?(?=[>"']\d{3,4}[<"'])[>"'](\d{3,4})[<"']
6:这更清楚地显示了正则表达式的另一个多余部分:你有一个先行断言(?=[>"']\d{3,4}[<"'])
,后跟完全相同的正则表达式[>"'](\d{3,4})[<"']
,因此可以完全删除前瞻。
最终结果:
(\d{13,16})[<"'].*?[>"'](\d{3,4})[<"']
或者,在C#中:
Regex regexObj = new Regex(@"(\d{13,16})[<""'].*?[>""'](\d{3,4})[<""']", RegexOptions.Singleline);