【问题标题】:How to fix this regex (matching dictionary entries)如何修复此正则表达式(匹配字典条目)
【发布时间】:2014-12-09 14:29:01
【问题描述】:

我正在使用具有如下定义的西班牙语词典:

l. a. c. Buitre, alimoche. adj. Persona alelada. (Cornago). GOICOECHEA. // 2. f. Persona torpe, despistada e irreflexiva. // 3. Estar mirando a los abantos. fr. fig. Ser despistado, soñador, no apercibirse de la realidad. Autol. RUIZ. // 4. f. esto es una prueba

以下规则适用:

  • 每个定义可以包含以下类别中的一个(并且永远不会超过一个):
    • l. a. c.
    • f.
    • m.
  • 类别始终位于定义的开头
  • 第一个定义从头开始,如果有更多定义,则以\\ n.开头,其中'n'是一个数字(可以多于一个数字)

对于我给出的示例,应该解析以下定义:

  1. (类别:l.a.c.)Buitre,alimoche。形容词角色阿莱拉达。 (玉米)。 GOICOECHEA
  2. (类别:f.)Persona torpe,despistada e impreflexiva。
  3. (无类别)Estar mirando a los abantos。 fr。如图。 Ser despistado, soñador, no apercibirse de la realidad。汽车鲁伊兹。
  4. (类别:f.)esto es una prueba

我正在尝试制作一个正则表达式来捕获每个定义(即 0 或 1 个类别 + 含义)。这就是我所拥有的

(?:(m\.|l\. a\. c\.|f\.) )?(.*?) (?:$|(?:\/\/ \d+. (?:(m\.|l\. a\. c\.|f\.) )?(.*?))+)

我正在测试它here这是我写的:

(?:
    (m\.|l\. a\. c\.|f\.)  <-- First: unnamed group containing the named group 
                                      for the category  and one space
)?
(.*?)                      <-- Named group for the meaning
(?:                        <-- Unnamed group for end of line OR another definition
   $                       <--- (end of line)
   |                       <--- (OR)
   (?:\/\/ \d+.            <--- (Definition separator & number)
       (?:(m\.|l\. a\. c\.|f\.) )?(.*?) <-- Another definition
   )+                                   <-- There may be more than one definition, so we add '+'
)

我有几个问题:

  • 我不知道为什么它不起作用。似乎最后一个捕获组(.*?) 直到下一个\\ 才扩展。我该如何解决?
  • (m\.|l\. a\. c\.|f\.) 组应该更大(类别更多)如何避免重复?
  • 我给出的正则表达式字符串中有一些重复,我该如何避免这种情况?

这是我的第一个重要的正则表达式示例,因此欢迎任何其他关于样式的评论或总体改进。

我的主要问题是为什么我的正则表达式不起作用。(这只是为了澄清......)

【问题讨论】:

  • 现在可能清楚了吗?
  • 第一个字典示例很棒 - 如果有更多行可以尝试使用正则表达式,那就太好了。
  • 这里还有几行(不过可能是其他类别...)pastebin.com/STsq16i9
  • (?:(m\.|l\. a\. c\.|f\.) )?(.*?)(?:$|(?:\/\/ \d+.) +) 对我来说效果更好,如果你让它变得贪婪的话。不太确定为什么原来的不起作用,但至于你想减少的重复,我认为你无能为力。
  • 感谢您提供所有详细信息并明确指出您想知道它为什么不起作用。人们往往会忽略这类问题,只是在提问者的脸上贴上一个全新的图案(哎呀,有时我也会这样做)。

标签: java regex parsing


【解决方案1】:

问题是最后一个捕获组是非贪婪的。

(?:
    (m\.|l\. a\. c\.|f\.)
)?
(.*?)
(?:
   $
   |
   (?:\/\/ \d+.
       (?:(m\.|l\. a\. c\.|f\.) )?
       (.*?) <-- this is non-greedy.
   )
)+

因此,它只会匹配空字符串。模式末尾的 + 没有做任何事情,因为它已经匹配了一次,这足以停止。

解决方法很简单:强制模式匹配整行。只需在末尾添加$

(?:(m\.|l\. a\. c\.|f\.) )?(.*?) (?:$|(?:\/\/ \d+. (?:(m\.|l\. a\. c\.|f\.) )?(.*?)))+$

编辑:不可能用单个正则表达式捕获每个类别和定义。如果您使用单个模式匹配整个字符串,每个捕获组将只包含它匹配的文本last,因此您将只能解析最后一个定义。

您可以使用此模式来匹配单个定义。

(?:^| \/\/ \d\. )(?:(?P<category>m\.|l\. a\. c\.|f\.) )?(?P<definition>.*?)(?:$|(?= \/\/ \d\.))

将其应用于字符串,直到它不再找到匹配以捕获所有定义。

while (matcher.find()){
   ... do something
}

Demo.


模式详解:

(?:
    ^ // match start of string
| // OR
     \/\/ \d\. // "\\ " literally, followed by a digit, a dot, and a space
)
(?:
    (?P<category> // in the named group "category", capture...
        m\.|l\. a\. c\.|f\. // one of "m.", "l. a. c.", "f."
    )  // and a space
)? // ...if possible.
(?P<definition> // in the named group "definition", capture...
    .*? // everything up to...
)
(?:
    $ // the end of the string
| // OR
    (?= // the start of the next definition. This needs to be enclosed in a lookahead assertion so as not to consume it.
         \/\/ \d\.
    ) 
)

【讨论】:

  • 这并不能解决问题,你可以在这里看到regex101.com/r/gH2uD9/3(我已经命名了这些组)。有很多定义没有被捕获
  • @Trollkemada:我想我误解了你想要达到的目标。我会更新我的答案。
  • 您错过了数字后面的+(允许多于一位数字),但其他答案很好!感谢您的努力。
  • 然而,为什么这不起作用? ((?X) 是 Java 7 中命名组的语法)ideone.com/K65Fjw
  • 您需要从命名组中删除XX 只是您要匹配的模式的占位符。
猜你喜欢
  • 2022-08-17
  • 2015-06-09
  • 2015-01-16
  • 1970-01-01
  • 2016-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多