【问题标题】:A regex for detecting multiline text if ended with a character如果以字符结尾,则用于检测多行文本的正则表达式
【发布时间】:2015-11-18 12:07:06
【问题描述】:

我有一个解析器,可以解析 PAWN 语言的代码。

我已经有一个正则表达式来解析该代码中的定义,典型的定义如下:

#define DEFINE_NAME DEFINE_VALUE

我使用以下正则表达式来检测它:

#define[ \t]+([^\n\r\s\\;]+)(?:[ \t]*([^\s;]+))?

现在到实际问题了。PAWN 语言仅在每行以斜杠结尾时才允许多行。所以这将是有效的:

#define DEFINE_NAME \
    DEFINE_VALUE    \
    CONTINUE_VALUE

如果有更多的斜线,可以继续前进。

Soo.. 我想要一个可以捕获可能的多行内容的正则表达式。

注意:我还需要它在单行定义中工作。所以请记住这一点。

我也使用 .NET,所以是的,这就是它的味道。

非常感谢任何帮助/贡献。 :D

【问题讨论】:

  • 只是想知道 - PAWN 是一种常规语言吗?虽然您可能能够解析示例中的 #define 之类的简单语句,但随着您的进步,您可能会发现使用正则表达式变得越来越困难。通常事情是使用标记器/解析器完成的。
  • 经过一些尝试,我收到了ugly regex,也许它可以帮助您开始。也许,它会说服你编写一个自己的高效解析器。
  • 您是否禁止使用内联 cmets?
  • 这是一种简单的无类型脚本语言。所以正则表达式会很好用。另外,它是 IDE 的解析器,而不是编译器。
  • 我认为下面的答案已经确定了,只需要测试它。

标签: .net regex vb.net macros multiline


【解决方案1】:

我们可以包含可选的斜杠和换行符:

(?:\\\r?\n[ \t]*)?

然后,为了允许多行以斜杠结尾,我们可以重复以下构造:

(?<value>(?>                  # Captures the DEFINE_VALUE
    [^\\\r\n;]+               #   Any char (except \ \n)
  |                           #  or
    \\[^\r\n][^\\\r\n;]*      #   "\" within value
)+)?                          #  (~unrolling the loop)
(?:\\\r?\n[ \t]*)?            # allow "\" for new line  

代码

Dim pattern As String = "^[ \t]*                    # beginning of line     " & vbCrLf &
                        "[#]define[ \t]+            # PAWN #define          " & vbCrLf &
                        "(?<name>[^\s\\;]+)         # DEFINE_NAME           " & vbCrLf &
                        "[ \t]*(?:\\\r?\n[ \t]*)?   # spaces and optional \ " & vbCrLf &
                        "(?>                        #                       " & vbCrLf &
                        "  (?<value>(?>             # DEFINE_VALUE          " & vbCrLf &
                        "    [^\\\r\n;]+   |        #  Any char -except \ \n" & vbCrLf &
                        "    \\[^\r\n][^\\\r\n;]*   #  \ within value       " & vbCrLf &
                        "  )+)?                     #  (~unrolling the loop)" & vbCrLf &
                        "  (?:\\\r?\n[ \t]*)?       # \ for new line        " & vbCrLf &
                        ")*                         # repeated for each line"

Dim re As Regex = new Regex( pattern, RegexOptions.Multiline Or
                                      RegexOptions.IgnorePatternWhitespace)
Dim text As String =    "#define DEFINE_NAME \"     & vbCrLf &
                        "       DEFINE VALUE\"      & vbCrLf &
                        "       CONTINUE VALUE"     & vbCrLf &
                        "#define TheName TheValue"
Dim mNum As Integer = 0
Dim matches As MatchCollection = re.Matches(text)

'Loop Matches
For Each match As Match In matches
    'get name
    Dim name As String = match.Groups("name").Value
    Console.WriteLine("Match #{0} - Name: {1}", mNum, name)

    'get values (in each capture)
    Dim captureCtr As Integer = 0
    For Each capture As Capture In match.Groups("value").Captures
        'loop captures for the Group "value"
        Console.WriteLine(vbTab & "Line #{0} - Value: {1}", 
                                captureCtr, capture.Value)
        captureCtr += 1              
    Next
    mNum += 1
Next

输出

Match #0 - Name: DEFINE_NAME
    Line #0 - Value: DEFINE_VALUE
    Line #1 - Value: CONTINUE_VALUE
Match #1 - Name: TheName
    Line #0 - Value: TheValue

ideone demo


  • 请注意,我正在使用 named groups (?&lt;name&gt;..) 和 (?&lt;value&gt;..)。这就是为什么它在代码中被引用为match.Groups("name")。

  • 此外,组(?&lt;value&gt;[^\s;]+) 对每一行重复。 Groups("value") 包含有关最后捕获的子字符串的信息。但是 Captures property 包含有关该组捕获的所有子字符串的信息。这是一个独特的 功能。
    这就是我循环match.Groups("value").Captures的原因。

【讨论】:

  • 非常感谢伙计。你是正则表达式的野兽。我不得不稍微修改一下以支持空格的值,这是我的最终正则表达式:^[ \t]*[#]define[ \t]+(?&lt;name&gt;[^\s\\;]+)[ \t]*(?:\\\s+)?(?&gt;(?&lt;value&gt;[^\\\n\r]+)[ \t]*(?:\\\s+)?)*
  • @Ahmad45123 这是故意的,因为我从你第一次尝试([^\s;]+) 时就假设了,因为不清楚#define 的正确语法应该是什么。我编辑了答案以考虑值中的空格。检查更新的正则表达式。
  • 是的,这是我的正则表达式中的一个错误,我很抱歉:P 再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-07
  • 1970-01-01
相关资源
最近更新 更多