你能将C ++ std :: regex表达式转换为C#表达式吗?

时间:2014-12-28 16:57:21

标签: c# c++ regex c++-cli

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

我在Visual Studio Express 2012中工作。看起来C#regex也需要\\

表达式:

//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);

1 个答案:

答案 0 :(得分:3)

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

C#中的

  

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

Regular Expression Options

相反,std::regex

  

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

C++ Reference - regex

要使std::regex表达式在C#中有效,您需要使用RegexOptions Enumeration并设置ECMAScript选项:

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

为表达式启用符合ECMAScript的行为。此值只能与IgnoreCase,Multiline和Compiled值一起使用。将此值与任何其他值一起使用会导致异常。

ECMAScript vs. Canonical Matching Behavior

  

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

     
      
  • 在匹配表达式中以不同方式指定字符类。 Canonical正则表达式默认支持Unicode字符类别。 ECMAScript不支持Unicode。
  •   
  • 必须使用每次捕获迭代更新具有自身反向引用的正则表达式捕获类。
  •   
  • 八进制转义和反向引用之间的歧义被区别对待。
  •   

<强>更新

在一些评论中,它建议在C#中使用逐字字符串(而不是逃避所有内容)。事实是,这不会起作用,因为:

  

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

C++ TR1 regular expressions

因此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));
    }
}