您可以将C++ std::regex 表达式转换为 C# 表达式吗?

本文关键字:表达式 转换 regex C++ std | 更新日期: 2023-09-27 18:35:24

我有 C# 代码通过正则表达式查找匹配并将其替换为 i# .但看起来C++表达式的工作方式与 C# 不同。请转换它或给出一些提示。

我在Visual Studio Express 2012工作。看起来 C# 正则表达式也需要''

表达 式:

//letter + possible letters or numbers without numbers before first letter    
"(?:^|[^''d])''b([a-zA-Z][a-zA-Z''d]*)" 
//exponencial number like 1.10E+5
"''d(''.?''d+)?E[+-]''d+" 
//next two is pretty obvious
"''d+''.''d+" 
"''d+"

C# 代码:

string input = "FGS1=(B+A*(5.01E+10))+A*10+(C*10.5)*51E-10+5.01E+10";
Regex r = new Regex(rExp);
var identifiers = new Dictionary<string, string>();
MatchEvaluator me = delegate(Match m)
{
    Console.WriteLine(m);
    var variableName = m.ToString();
    if (identifiers.ContainsKey(variableName))
    {
        return identifiers[variableName];
    }
    else
    {
        i++;
        var newVariableName = "i" + i.ToString();
        identifiers[variableName] = newVariableName;
        return newVariableName;
    }
};
input = r.Replace(input, me);

您可以将C++ std::regex 表达式转换为 C# 表达式吗?

是和否。您不必将正则表达式从 std::regex 转换为 C# 。您所需要的只是告诉C#使用不同的行为。原因和方法如下:

C#

默认情况下,正则表达式

引擎在将正则表达式模式与输入文本匹配时使用规范行为。

正则表达式选项

相反,std::regex

默认情况下,此库中的函数使用 ECMAScript 语法。

C++ 参考资料 - 正则表达式

要使std::regex表达式在C#中工作,您需要使用 RegexOptions 枚举并设置 ECMAScript 选项:

new Regex(pattern, RegexOptions.ECMAScript | RegexOptions.IgnoreCase);

为表达式启用符合 ECMAScript 的行为。此值只能与"忽略大小写"、"多行"和"已编译"值结合使用。将此值与任何其他值一起使用会导致异常。

ECMAScript vs. 规范匹配行为

ECMAScript 和规范正则表达式的行为不同 在三个方面:

  • 字符类在匹配表达式中的指定方式不同。默认情况下,规范正则表达式支持 Unicode 字符类别。ECMAScript 不支持 Unicode。
  • 具有自身反向引用的正则表达式捕获类必须随着每次捕获迭代进行更新。
  • 八进制转义和反向引用之间的歧义处理方式不同。

更新:

在某些评论中,建议在C#中使用逐字字符串(而不是转义所有内容)。事实是,这是行不通的,因为:

正则表达式处理(使用 std:regex)在C++中不如在具有内置正则表达式支持的语言(如 Perl)中方便。一个原因是转义序列。若要将反斜杠 '' 发送到正则表达式引擎,必须在源代码中键入 ''。例如,考虑这些定义。

C++ TR1 正则表达式

因此,OP 定义的模式是正确的。


例:

C#

var input = "123";
var pattern = "''d";
var result1 = Regex.Replace(input, pattern, "_", RegexOptions.ECMAScript); // produces "___"
var result2 = RegexTest.Replace(input, pattern, "_"); // produces "___"

C++/CLI

String^ RegexTest::Replace(String^ input, String^ pattern, String^ replacement) {
    using namespace Runtime::InteropServices;
    const char* p_input = (const char*)(Marshal::StringToHGlobalAnsi(input)).ToPointer();
    const char* p_pattern = (const char*)(Marshal::StringToHGlobalAnsi(pattern)).ToPointer();
    const char* p_replacement = (const char*)(Marshal::StringToHGlobalAnsi(replacement)).ToPointer();
    try {
        std::string _input(p_input);
        std::string _replacement(p_replacement);
        std::regex re = std::regex(p_pattern);
        std::string result = std::regex_replace(_input, re, _replacement);
        return gcnew String(result.c_str());
    } finally {
        Marshal::FreeHGlobal(IntPtr((void*)p_pattern));
        Marshal::FreeHGlobal(IntPtr((void*)p_input));
        Marshal::FreeHGlobal(IntPtr((void*)p_replacement));
    }
}