【问题标题】:Visual Basic .net Regex match does not work - despite working on a testing tool?Visual Basic .net 正则表达式匹配不起作用 - 尽管正在使用测试工具?
【发布时间】:2013-02-25 07:10:10
【问题描述】:

我有一个非常简单的问题要问别人 - 但我自己无法回答。我有一个正则表达式模式,适用于两个不同的在线测试人员,其中一个是基于 .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 标记之间的所有项目。

感谢您这么快的回复!

【问题讨论】:

  • 请发布您要匹配的文本、预期结果和实际结果。
  • 会不会抛出异常
  • @JonSkeet 好点乔恩,已添加。哦,只是为了爬行...我最近收到了您最新的 C# 深度电子书。好一个!您之前的一篇对闭包的精彩描述从那时起影响了我的编程。
  • @Richard:我添加了一个新答案,我解释了为什么它不匹配并给了你一个解决方案。
  • @Matt 在紧急呼叫客户后刚回到办公室。如果可以的话,我会在回家时检查一下。谢谢 - 我的 iPad 做不到 :)

标签: .net regex vb.net


【解决方案1】:

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

如果您将其更改为(.+?),您应该会获得多个条目。然后要在&lt;pre&gt; 标记中查找文本,您需要获取match.Groups[2] 的值。 ? 使 .+ 不情愿 - 它匹配尽可能少的字符。

此外,顺便说一下,尚不清楚(?m) 在这里的目的是什么。

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

【讨论】:

  • 我自己很快就会玩这个。正如我在下面提到的,我的兄弟昨晚解决了这个问题……而且他是一个非常新的编码新手。 iPad 我承认在这方面不确定,直到今晚我再次使用它。我无法让他的正则表达式在 VS 中工作,但它在在线正则表达式测试器 Rubular 中运行良好。
  • 出于好奇,VB在使用非贪婪表达式时是否有类似PCRE的回溯限制?
  • @Jack:不知道,恐怕。 (但这在 .NET 中是一个限制,而不是在 VB 中。)
【解决方案2】:

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

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

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

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

关于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 次。

调查结果:

'在一个文件中有很多这样的'

' 查找所有标签 '

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

【讨论】:

  • 他不需要逃避&lt;&gt; 也不需要/。它们不是特殊字符,除非在复合语法 (?&lt;name&gt;).
  • @Teejay:谢谢你的提示,我试试看。
  • @Matt,有趣的是他也想访问这些组;我在自己挖掘它的过程中删除了一个事实。这是一个非常完整的答案,马特,感谢您投入的时间。我今晚将应用它。
  • @Matt 已经尝试过了。这是一种享受!谢谢你。目前,我认为正则表达式并不是最容易掌握的最基础知识——纯粹是因为我只需要在少数简单的情况下使用它们。
  • 很高兴听到我能为您提供帮助。 @Teejay:我已经尝试了你的建议,你是对的 - 不需要转义字符。代码示例会相应更新。
【解决方案3】:

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

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

除此之外,我想你的意思是&lt;pre&gt;(不是&lt;/pre&gt;)在and there之后...

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


此外,尚不清楚为什么 (?m)/B(以及为什么在结尾而不是开头)。

【讨论】:

  • Regex 是我哥哥昨晚深夜为回答我给他设置的挑战而构建的。他四个星期前开始编码,以前从未做过,每天在超市工作 12 小时。我希望能帮助他换工作。他今年 23 岁。不幸的是,我自己还不是 Regex 方面的专家 :)。我在 Rubular 上测试了原版,所以我怀疑它的实现略有不同。今晚我有很多答案要挖掘。谢谢大家!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-03
  • 1970-01-01
相关资源
最近更新 更多