gpt4 book ai didi

c# - 轻型 HTML 部分匹配优化

转载 作者:太空宇宙 更新时间:2023-11-03 12:11:31 25 4
gpt4 key购买 nike

我从 API 接收到一些文本,其中包含一些 HTML,即 <span> s 和 <a>秒。我将使用这些部分来填写 FormattedText Xamarin.Forms 的属性 Label .

我有以下代码可以正常工作,但看起来效率很低,每个循环有一个外部正则表达式和三个以上。

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

鉴于此输入:

one<span class=\"a-class\">two</span>three<a href=\"#a-link\">four</a>five

正确产生:

one -> 
two -> a-class
three ->
four -> #a-link
five ->

代码:

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}");
}
}

最佳答案

以下代码将使用单个正则表达式生成所需的输出,尽管正则表达式有点复杂:

    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}");
}

让我们分解正则表达式。这是没有转义引号的完整正则表达式(当我从我的正则表达式测试器复制到逐字的 C# 字符串时,我不得不转义双引号):

^(?<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:这假设原始字符串没有 \ s 在里面,那些只是为了转义示例 C# 代码中的双引号。如果字符串将有 \在其中,需要调整正则表达式以查找 \ s 在上面的第二和第三部分。

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

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

关于c# - 轻型 HTML 部分匹配优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52067960/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com