代码之家  ›  专栏  ›  技术社区  ›  Jon Cage

如何替换正则表达式中的匹配组?

  •  0
  • Jon Cage  · 技术社区  · 6 年前

    给定一些输入数据:

    <somexml>
        <User Name="MrFlibble">
            <Option Name="Pass">SomeSaltedPassword</Option>
            <Option Name="Salt">Salt</Option>
            <tag1></tag1>
            <Permissions>
                <Permission Dir="E:"></Permission>
            </Permissions>
        </User>
        <User Name="MrFlobble">
            <Option Name="Pass">SomeOtherSaltedPassword</Option>
            <Option Name="Salt">Salt</Option>
            <tag1></tag1>
            <Permissions>
                <Permission Dir="C:"></Permission>
            </Permissions>
        </User>
    </somexml>
    

    我想替换第一个没有 C: 用户区域中的权限(在本例中 MrFlibble )与 Jon SomeSaltedPassword 具有 MyNewSaltedPassword 使用.net framework正则表达式可以得到以下结果:

    <somexml>
        <User Name="Jon">
            <Option Name="Pass">MyNewSaltedPassword</Option>
            <Option Name="Salt">Salt</Option>
            <tag1></tag1>
            <Permissions>
                <Permission Dir="E:"></Permission>
            </Permissions>
        </User>
        <User Name="MrFlobble">
            <Option Name="Pass">SomeOtherSaltedPassword</Option>
            <Option Name="Salt">Salt</Option>
            <tag1></tag1>
            <Permissions>
                <Permission Dir="C:"></Permission>
            </Permissions>
        </User>
    </somexml>
    

    <User Name="(.*)">.*<Option Name="Pass">(.*)<\/Option>.*<Option Name="Salt">(.*)<\/Option>.*<\/User>
    

    The docs 所有这些似乎都建议用特定的新文本替换对原始文本的修改,而不是多个特定命名的组。

    3 回复  |  直到 6 年前
        1
  •  2
  •   JGNI    6 年前

    在任何情况下都不要尝试使用正则表达式解析XML,除非您希望调用 rite 6 6 6

    使用XML解析库请参见 this page 为了找到一些方法。

        2
  •  1
  •   Alexander Petrov    6 年前

    将对System.Xml.Linq库的引用添加到项目中。
    打开以下名称空间

    using namespace System;
    using namespace System::IO;
    using namespace System::Xml::Linq;
    

    //auto xml = XElement::Parse(input); // input - string containing your xml
    auto xml = XElement::Load(L"test.xml");
    
    for each (auto user in xml->Elements(L"User"))
    {
        if (user->Element(L"Permissions")->Element(L"Permission")->Attribute(L"Dir")->Value != L"C:")
        {
            user->Attribute(L"Name")->Value = L"Jon";
    
            for each(auto option in user->Elements(L"Option"))
            {
                if (option->Attribute(L"Name")->Value == L"Pass")
                {
                    option->Value = L"MyNewSaltedPassword";
                }
            }
        }
    }
    
    Console::WriteLine(xml);
    //xml->Save(L"result.xml");
    
        3
  •  1
  •   Alexander Petrov    6 年前

    using namespace System;
    using namespace System::IO;
    using namespace System::Text::RegularExpressions;
    

    匹配评估器方法:

    String^ Evaluate(Match^ m)
    {
        if (m->Groups[L"dir"]->Value != L"C:")
            return L"Jon" + m->Groups[L"mid1"] + L"MyNewSaltedPassword" + m->Groups[L"mid2"] + m->Groups[L"dir"];
        else
            return m->Groups[L"name"]->Value + m->Groups[L"mid1"] + m->Groups[L"pass"] + m->Groups[L"mid2"] + m->Groups[L"dir"];
    }
    

    auto input = File::ReadAllText(L"test.xml");
    
    auto pattern = gcnew String(R"(
    (?<= <User \s Name = " )
    (?'name' .+? )
    (?= "> )
    
    (?'mid1' .+? )
    
    (?<= <Option \s Name = "Pass"> )
    (?'pass' .+? )
    (?= </Option> )
    
    (?'mid2' .+? )
    
    (?<= <Permission \s Dir = " )
    (?'dir' .+? )
    (?= "> )
    )");
    
    auto options = RegexOptions::IgnorePatternWhitespace | RegexOptions::Singleline;
    
    auto evaluator = gcnew MatchEvaluator(Evaluate);
    auto result = Regex::Replace(input, pattern, evaluator, options);
    
    Console::WriteLine(result);
    
    推荐文章