使用c#和Regex查找并包围一些html文本中的所有单词和数字
本文关键字:文本 数字 单词 html Regex 查找 包围 使用 | 更新日期: 2023-09-27 18:14:55
我需要在加载的html文本中包含一个span,该span将唯一标识每个单词。问题是有些内容没有被我的正则表达式模式处理。我目前的问题包括…
1)特殊的html字符如” “
被视为单词。
2)货币价值。例如2500美元最终成为"2"500"(我需要"2500美元")
3)双连字符的单词。例如one-legged-man。最后变成"独腿"人"
我是正则表达式的新手,在看了其他各种帖子之后,得出了以下模式,除了上述例外情况外,它似乎适用于所有事情。目前我得到的是:
string pattern = @"(?<!<[^>]*?)'b(''w+)|('w+['-]'w+)|('w+')|('w+)'b(?![^<]*?>)";
string newText = Regex.Replace(oldText, pattern, delegate(Match m) {
wordCnt++;
return "<span data-wordno='" + wordCnt.ToString() + "'>" + m.Value + "</span>";
});
我如何修复/扩展上述模式以满足这些问题,或者我应该一起使用不同的方法?
你在这里遇到的一个基本问题是html不是一种"常规语言"。这意味着html足够复杂,您总是能够提出任何正则表达式都无法识别的有效html。这不是写一个更好的正则表达式的问题;这是一个正则表达式无法解决的问题。
你需要的是一个专门的html解析器。你可以试试这个包。还有很多其他的,但是htmllagilitypack是非常流行的。编辑:下面是一个使用htmllagilitypack的示例程序。解析HTML文档时,结果是一个树(即DOM)。在DOM中,文本存储在文本节点中。因此,像<p>Hello World<'p>
这样的东西被解析成一个节点来表示p标记,用一个子文本节点来保存"Hello World"。因此,您要做的是找到文档中的所有文本节点,然后,对于每个节点,将文本分成单词,并用span将单词括起来。
可以使用xpath查询搜索所有文本节点。我下面的xpath是/html/body//*[not(self::script)]/text()
,它避免了html头部和正文中的任何脚本标记。
class Program
{
static void Main(string[] args)
{
var doc = new HtmlDocument();
doc.Load(args[0]);
var wordCount = 0;
var nodes = doc.DocumentNode
.SelectNodes("/html/body//*[not(self::script)]/text()");
foreach (var node in nodes)
{
var words = node.InnerHtml.Split(' ');
var surroundedWords = words.Select(word =>
{
if (String.IsNullOrWhiteSpace(word))
{
return word;
}
else
{
return $"<span data-wordno={wordCount++}>{word}</span>";
}
});
var newInnerHtml = String.Join("", surroundedWords);
node.InnerHtml = newInnerHtml;
}
WriteLine(doc.DocumentNode.InnerHtml);
}
}
修复1)通过添加"负向后看断言" (?<!'&)
。我相信在上述原始模式的第1、第3和第4个选项的开头需要它们。
通过在pattern的末尾添加一个新的替代|('$?('d+[,.])+'d+)'
来修复2)。这也可以同时处理非美元数和小数。
('w+['-]'w+)
选项增强为read代替(('w+['-])+'w+)
。