1

我确定这个问题已经在某个地方被问过(也许在这里),但我找不到任何信息,这可能是因为我不确定如何准确描述它。

本质上,我正在寻找高级查找和替换。更换我确信我可以弄清楚它什么时候可以使用,但现在我无法找到工作。

在一个应用程序中,有很多 htm 文件被加载。用户选择一个文件并对其执行操作。完成此操作后,我希望系统再扫描一次文件以确保没有问题。例如,此字符串可能存在于 htm 文件中:

<?strange_tag_start 
     name="var_value" ?>Name<?strange_tag_end ?>

而且,是的,它可以像这样被打破。以上不是问题,除非发生这种情况:

<?strange_tag_start 
     name="var_value" ?><?strange_tag_start 
     name="var_value" ?>Name<?strange_tag_end ?><?strange_tag_end ?>

换行符可能不同。我想要做的是在文档中搜索包含<?strange_tag然后包含<?strange_tag_end ?>. 如果找到这些,我想在字符串中检查是否有 another<?strange_tag_start或 another <?strange_tag_end ?>

我最初尝试读取文件并获取特定值的每个索引,然后尝试比较它们。但是,文件中可能存在以下内容,这些内容完全可以,但系统会找到它们并为我标记它们:

<?strange_tag_start 
     name="var_value" ?>Name<?strange_tag_end ?> There is other text here
and some more text on another line. Then this <?strange_tag_start name="var_value"
             ?>Name<?strange_tag_end ?> is present.

它归结为一个系统(例如存在于某些应用程序中),其中指定了字符串的开头,指定了字符串的结尾,然后系统检查它是否包含字符串。

如果这没有意义或者您需要更多说明,我可以这样做。

更新

让我澄清一下。我有以下多行字符串:

I want to preserve<?start_foo  
                bar="value" ?> the content  
<?start_baz qux="value" ?>Name  
<?end-baz_qux ?>that is between weird tags.

我想找到<?start_foo bar="value" 我也想找到<?end-baz_qux ?>(注意:其中可能有两个彼此相邻。)找到这些后,我想检查该字符串中是否有另一个<?start_foo bar=(注意:该标签中的“值”可以也不同。)然后我想删除不应该存在的中间内容,所以我最终得到:

I want to preserve<?start_foo  
                bar="value" ?> the content 
<?end-baz_qux ?>that is between weird tags.

这是另一个示例,希望可以使其更清楚:

Back <?rh-udv_start name="ctrl_btn" ?><?rh-udv_start name="ctrl_btn" 
    ?>button<?rh-udv_end ?><?rh-udv_end ?> to

完成搜索后,我应该得到这个:

Back <?rh-udv_start name="ctrl_btn" ?>button<?rh-udv_end ?> to

本质上,我正在寻找一种说法:

  1. 使用 VALUE_X 查找“开始”的字符串(误导为“开始”可能位于字符串的中间)。
  2. 如果找到,则在其后找到 VALUE_Y(如果有 VALUE_X,则应始终找到)。
  3. 检查 VALUE_Y 之后是否还有另一个 VALUE_Y。
  4. 检查 VALUE_X 到 VALUE_Y 的字符串内部是否包含另一个 VALUE_X。
  5. 如果还有另一个 VALUE_X,请将其删除。如果紧跟在 VALUE_Y 之后有一个 VALUE_Y,则删除第二个 VALUE_Y。
4

2 回答 2

2

我相信

<\?.*?\?>

可以找到大多数正则表达式风格的标签(包括 Visual Studio 的 - 不确定你使用的是哪个)。

如果你也想替换奇怪标签之间的内容,那你能给我们举一个更现实的例子吗?为了提供正确的正则表达式,准确了解您要匹配的内容(或一些非常接近的近似值)至关重要。例如

<?start_strange_tag blah="foo"?>Name<?end_strange_tag?>

<?foo bar="baz"?>Name<?/foo?>

这不同于

<?start_foo bar="baz"?>Name<?foo_end?>

等等。

更新

根据您在下面的评论,我将假设您的文档如下所示:

I want to preserve<?start_foo  
                    bar=\"value\" ?> the content  
<?start_baz qux=\"value\" ?>Name  
<?end-baz_qux ?>that is not between weird tags.

并且您希望结果是:

I want to preserve the content  
that is not between weird tags.

我还将假设您使用的是 .NET 正则表达式程序集(而不是 Visual Studio 内置的正则表达式。是的,它们是不同的。)

如果是这样的话,那么你可以使用这样的东西:

static void Main( string[] args )
{

    string l_input =
        "I want to preserve<?start_foo \n" + 
        "                    bar=\"value\" ?> the content\n" +
        "<?start_baz qux=\"value\" ?>Name\n" +
        "<?end-baz_qux ?>that is not between weird tags.";

    string[] l_singleTags = { "foo" };
    string[] l_multiTags = { "baz" };

    // Removing the single tags is easy:

    foreach ( var l_singleTag in l_singleTags )
        l_input = Regex.Replace( l_input, @"<\?start_" + Regex.Escape( l_singleTag ) + @"\b.*?\?>", "", RegexOptions.Singleline );

    // Removing the multi tags is not too bad:

    foreach ( var l_multiTag in l_multiTags )
        l_input = Regex.Replace( l_input, @"<\?start_" + Regex.Escape( l_multiTag ) + @" (?<param>\w+).*?\?>.*?<\?end-" + Regex.Escape( l_multiTag ) + @"_\k<param>.*?\?>", "", RegexOptions.Singleline );

    Console.WriteLine( l_input );

    Console.ReadKey( true );

}

l_input变成:

I want to preserve the content  
that is not between weird tags.

更新 2

为了响应您的问题更新,请尝试以下代码:

static void Main( string[] args )
{

    string l_input =
        "Back <?rh-udv_start name=\"ctrl_btn\" ?><?rh-udv_start name=\"ctrl_btn\"" +
        "   ?>button<?rh-udv_end ?><?rh-udv_end ?> to";

    l_input = Regex.Replace( l_input, @"<\?(?<tagname>[-a-z]+_[a-z]+).*?\?>(?=<\?\k<tagname>)", "", RegexOptions.Singleline );

    Console.WriteLine( l_input );

    Console.ReadKey( true );

}

l_input变成:

Back <?rh-udv_start name="ctrl_btn"   ?>button<?rh-udv_end ?> to

它只是查找重复标签并将其删除。例如:

<?a_start foo="bar"?><?a_start    foo="bar"
?>

第一个标签将被删除,只留下:

<?a_start    foo="bar"
?>

结束标签也是如此。代码不会容忍标签之间的空间或内容(在这种情况下它不会删除任何一个标签)。随意使用该示例,直到您拥有所需的内容。

于 2013-01-17T18:26:43.313 回答
0

您可以为此使用Html Agility Pack。我已经将它用于类似的事情,在 HTML 中查找引用并将 ID 替换为序数。在我的情况下,搜索和替换如下所示:

var doc = new HtmlDocument();
doc.LoadHtml(html);
// find using xpath expression
var citeNodes = doc.DocumentNode.SelectNodes("//cite[@data-citationid]");
foreach (var node in citeNodes)
{
    // do some other stuff
    node.Name = "a";
    node.SetAttributeValue("id", "r" + citation.CitationId);
    node.InnerHtml = "[" + citation.Ordinal + "]";
}
return doc.DocumentNode.InnerHtml;
于 2013-01-17T18:30:00.677 回答