2

我对某人有一个愚蠢的简单问题 - 但我自己无法回答。我有一个正则表达式模式,适用于两个不同的在线测试器,其中一个是基于 .net 的。

然而在这里它找不到匹配项。任何人都可以帮忙吗?目的是过滤一个可爱的 F# 秘籍页面,使其可打印:)。

我正在指导我最小的弟弟,他正在学习编程的第 4 周——这是他的职责,我承认这让我很困惑!任何帮助我都会非常感激!!

  Public Function FindCode(input As String)
    Dim pattern As String = "(?m)(<pre>)(.+)(<\/pre>)\B"
    Dim output As New Dictionary(Of Integer, String)
    Dim count As Integer

    For Each match As Match In Regex.Matches(input, pattern)
        output.Add(count, match.Value)
        count += 1
    Next
Return output.count
End Function

我没有得到执行,我没有得到匹配。

一个例子是

Some random markup <pre> and this stuff in the middle is what I'm after </pre> and there </pre> lots of these in one file </pre> which when I use Regexhero <pre> finds all the tags  </pre> 

这样,我们可能会使用组来列出 pre /pre 标记之间的所有项目。

感谢您的快速回复!

4

3 回答 3

3

我认为问题是(.+)- 默认情况下是贪婪的,所以它尽可能匹配 - 包括中间</pre>部分。

如果你把它改成(.+?)你应该得到多个条目。然后要在<pre>标签中查找文本,您需要获取 的值match.Groups[2]。这?让人.+ 不情愿——它匹配尽可能少的字符。

此外,顺便说一下,目前还不清楚(?m)这里要实现什么。

(哦,当然,使用正则表达式解析 HTML 通常是个坏主意……)

于 2013-02-25T08:18:11.003 回答
1

首先,我尝试了您使用Expresso提供的表达式,然后在LinqPad中尝试了- 两者都返回了整个字符串,这不是您想要匹配的。我看到 2 个问题,为什么它没有显示预期的结果:

  1. 正则表达式本身
  2. 示例字符串中的问题(标签不是成对的,即每个标签都<pre>必须由 关闭</pre>

除此之外,我建议对代码进行一些改进:

  1. 更改匹配方式(下面的示例使用正则表达式选项,并允许分组)
  2. 添加 tagName 作为参数,添加参数以允许包含或排除标签
  3. 返回集合而不是计数值

看一下代码,它运行良好(我为LinqPad添加了一些可选的、注释掉的.Dump()语句,以防您想打印出用于调试的值):

Public Function FindCode(input As String, tagName as string, includeTags as boolean)
    Const grpName as string = "pregroup"
    Dim pattern As String = "(<"+tagName+">)(?<"+grpName+">(\s|\w|')+)(</"+tagName+">)"  
    Dim output As New Dictionary(Of Integer, String)
    Dim count As Integer
    
    Dim options as RegexOptions = RegexOptions.IgnoreCase _
          or RegexOptions.IgnorePatternWhitespace _
          or RegexOptions.MultiLine or RegexOptions.ExplicitCapture
    ' options.Dump("options")
    Dim rx as Regex = new Regex(pattern, options)
    For Each m As Match In rx.Matches(input)
        Dim val as string=nothing
        if (includeTags) 
            val = m.Value
        else
            if(m.Groups(grpName).Success)
                val = m.Groups(grpName).Value 
            end if
        end if
        if not (val is nothing)
            ' val.Dump("Found #" & count+1)
            output.Add(count, val)
            count += 1
        end if
    Next    
    Return output
End Function

关于表达:

  • 我使用(\s|\w)+而不是.+,因为它只包含空格和字母数字字符,而不是括号,因此不包含标签
  • 通过使用(其中 nn 是字符的十六进制代码)转义与正则表达式语法的特殊字符冲突\xnn的字符 - 注意:这在这里不适用
  • 使用组名轻松访问标签的内容

关于Regex代码:我添加了参数includeTags,以便您可以看到差异(false不包括它们,true包括它们)。请注意,您应该始终正确设置 RegexOptions,因为它会影响表达式的匹配方式。

最后,这是主要代码:

Sub Main
    dim input as string = "Some random markup <pre> and this stuff in the middle is what I'm after </pre> and there <pre> lots of these in one file </pre> which when I use Regexhero <pre> finds all the tags  </pre>"
    dim result = FindCode(input, "pre", false)
    dim count as integer = result.Count()
    Console.WriteLine(string.Format("Found string {0} times.", count))
    Console.WriteLine("Findings:")
    for each s in result
        Console.WriteLine(string.format("'{0}'", s.Value))
    next
End Sub

这将输出:

找到字符串 2 次。

发现:

'很多这些在一个文件中'

' 找到所有标签 '

但是,还有一个问题:为什么第一个不<pre>...</pre>匹配?看一下子字符串I'm after- 它包含'不匹配的内容,因为它既不是空格也不是字母数字。您可以通过在正则表达式中指定来添加它(\s|\w|'),然后它将显示所有 3 个字符串。

于 2013-02-25T10:14:16.127 回答
1

我得到了正确的输出(对于给定的正则表达式),一个匹配包含:

<pre> and this stuff in the middle is what I'm after </pre> and there </pre> lots of these in one file </pre> which when I use Regexhero <pre> finds all the tags </pre>

除了我想你的意思是<pre>(不是</pre>)之后and there......

可能您想使用(.+?),因为 + 默认情况下是贪婪的。


此外,目前尚不清楚为什么(?m)/B(以及为什么最后但不是开始)。

于 2013-02-25T08:19:43.077 回答