首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >轻量化HTML零件匹配优化

轻量化HTML零件匹配优化
EN

Stack Overflow用户
提问于 2018-08-29 00:42:24
回答 1查看 48关注 0票数 2

我从一个包含一些HTML的API中接收到一些文本,即<span><a>,我将使用这些部分来填充Xamarin.Forms LabelFormattedText属性。

下面的代码工作得很好,但是看起来效率很低,有一个外部正则表达式,每个循环多三个。

我想知道是否有更高级的正则表达式可以用来更好地分块,以获取我需要的classhref属性。

鉴于这一投入:

代码语言:javascript
运行
复制
one<span class=\"a-class\">two</span>three<a href=\"#a-link\">four</a>five

正确地产生:

代码语言:javascript
运行
复制
one -> 
two -> a-class
three -> 
four -> #a-link
five ->

代码:

代码语言:javascript
运行
复制
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class Program
{
    public class StringPart
    {
        public string Text { get; set; }
        public string Class { get; set; }
        public string Link { get; set; }

        public bool IsClass => !string.IsNullOrEmpty(Class);
        public bool IsLink => !string.IsNullOrEmpty(Link);

        public string Info
            => IsClass ? Class : IsLink ? Link : string.Empty;
    }

    public static void Main()
    {
        var text = "one<span class=\"a-class\">two</span>three<a href=\"#a-link\">four</a>five";

        var parts = new List<StringPart>();

        var idx = 0;

        // Matches '<span class=\"a-class\">two</span>'
        // &       '<a href=\"#a-link\">four</a>'
        foreach (Match match in new Regex($"<(.*?)>(.*?)</(.*?)>").Matches(text))
        {
            // preceeds match
            parts.Add(new StringPart { Text = text.Substring(idx, match.Index - idx) });

            // a match, has either span or a props
            // 3 more regex, though
            parts.Add(new StringPart
            {
                Text = Regex.Replace(match.Value, "<.*?>", string.Empty),
                Link = Regex.Match(match.Value, "(?<=href=\\\")[\\S]+(?=\\\")").Value,
                Class = Regex.Match(match.Value, "(?<=class=\\\")[\\S]+(?=\\\")").Value
            });

            // move idx for next preceeding part
            idx = match.Index + match.Length;
        }

        // remaining after last match
        parts.Add(new StringPart { Text = text.Substring(idx) });

        // dump
        foreach (var p in parts)
            Console.WriteLine($"{p.Text} -> {p.Info}");        
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-29 02:26:55

下面的代码将使用单个regex生成所需的输出,尽管regex有点复杂:

代码语言:javascript
运行
复制
    public static void Main()
    {
        var testString = "one<span class=\"a-class\">two</span>three<a href=\"#a-link\">four</a>five";

        var matches = new Regex(@"^(?<Text>.+?)<|span class=""(?<Class>.*?)"">(?<Text>.+?)<\/span|a href=""(?<Link>.*?)"">(?<Text>.+?)<\/a|>(?<Text>.+?)<|>(?<Text>.+?)$").Matches(testString);

        var parts = from m in matches.Cast<Match>()
                    select new StringPart
                    {
                        Text = m.Groups["Text"].Value,
                        Class = m.Groups["Class"].Value,
                        Link = m.Groups["Link"].Value
                    };

        // dump
        foreach (var p in parts)
            Console.WriteLine($"{p.Text} -> {p.Info}");
    }

让我们把横梁拆了。下面是没有转义引号的完整正则表达式(当我从regex测试器复制到逐字C#字符串时,必须转义双引号):

代码语言:javascript
运行
复制
^(?<Text>.*?)<|span class="(?<Class>.*?)">(?<Text>.*?)<\/span|a href="(?<Link>.*?)">(?<Text>.*?)<\/a|>(?<Text>.+?)<|>(?<Text>.+?)$

表达式有五个部分,由|分隔。每个部分包含一个或多个命名组,它们捕获我们为该部分所关心的数据。

命名组具有以下格式:(?<Name>...)

以下是五个部分:

  1. ^(?<Text>.+?)<:匹配起始文本直到并包含第一个<
  2. span class="(?<Class>.*?)">(?<Text>.+?)<\/span:匹配<span>元素并捕获文本和类
  3. a href="(?<Link>.*?)">(?<Text>.+?)<\/a:匹配<a>元素并捕获文本和链接
  4. >(?<Text>.+?)<:匹配文本b/t两个HTML元素,包括><
  5. >(?<Text>.+?)$:匹配结束文本,包括最后一个>

注1:如果字符串中没有HTML元素(例如,"one"),这将返回零匹配。最好单独处理那个特殊情况。

注2:这假设原来的字符串中没有\,而这些字符串放在那里只是为了转义示例C#代码中的双引号。如果字符串中包含\,则需要对正则表达式进行调整,以查找上面第2和第3部分中的\s。

(这里是我以前提出的测试器中的正则表达式:https://regex101.com/r/9C5dmy/2/ --除了在复制到C#代码时转义双引号之外,我还可以将所有"Text*“组名重命名为"Text”-- regex101.com不允许重复的组名,但是C#允许,并且所有命名为"Text“的"Text*”组都简化了逻辑。)

更新:将“文本”组从(?<Text>.*?)切换到(?<Text>.+?),以确保一个或多个字符以避免空字符串匹配。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52067960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档