【问题标题】:Regex not capturing date正则表达式未捕获日期
【发布时间】:2014-01-27 23:25:45
【问题描述】:

我有一个目前可以正常工作的正则表达式。但现在我想添加它以捕获日期。

当前正则表达式:

(?<GeneralHelp>^/help\s*)?
(?:/client:)
(?<Client>\w*)
(?:(?:\s*/(?<ClientHelp>help))*)*
(?:(?:\s*/)(?<Modules>createHistory)(?:(?:\s*/(?<ModuleHelp>help))*)*)*

我添加到最后:

(?:(?:\s*/)(?<StartDate>^([0]?[1-9]|[1|2][0-9]|[3][0|1])[. -]([0]?[1-9]|[1][0-2])[. -]([0-9]{4}|[0-9]{2})$))*)*
(?:(?:\s*/)(?<EndDate>^([0]?[1-9]|[1|2][0-9]|[3][0|1])[. -]([0]?[1-9]|[1][0-2])[. -]([0-9]{4}|[0-9]{2})$))*)*

使用下面的示例,它不会获取日期,但它会匹配其他所有内容。

/client:testClient/createHistory/11-11-2013/11.11.2013

此正则表达式用于在控制台应用程序的字符串数组参数中分解Main 一个字符串。我的团队中没有人在正则表​​达式中“流利”,我们也没有时间变得流利。我们尽我们所能工作,而我今天想到的这个补充可能会给我们的项目带来更大的问题,而且我们的时间不多了。因此,我们将不胜感激。

【问题讨论】:

  • 您应该添加一些应用正则表达式的示例数据。您是否故意没有在[. -] 中逃脱.-?据我所知,这些仍应被解释,因此. 将匹配任何字符,而不仅仅是句点。
  • @Mario:不,[。 -] 表示“匹配 .、空格或 -”。因为“-”是字符类中的最后一个,所以无意匹配范围没有问题。
  • @Mario:在方括号内,. 只是一个点,- 只是一个连字符,如果它紧挨着一个括号。 @Kendra:你在(?:\s*/) 上使用非选择性括号有什么原因吗?
  • 好的,知道-,但不确定.。不过说实话也没什么意义。
  • @KendraBall 我建议你学习一些正则表达式,而不是盲目地从其他人那里使用它,因为你已经发现了一些非常明显的错误。

标签: c# regex date


【解决方案1】:

首先,您的正则表达式中的^ 表示“字符串开头”,即您只想匹配字符串开头的日期(这对您来说不正确)。所以删除它。与“$”相同,表示“字符串结束”。

其次,[0|1] 表示“匹配字符 0、| 或 1”。您可能希望 [01] 表示“匹配字符 0 或 1”。

第三,你的两个正则表达式都有一个额外的右括号和一个不匹配的左括号。

第四,作为一般风格点,[0]0 相同,所以这里的方括号是多余的。

所以你的(不完全是!)“固定”正则表达式是:

(?:(?:\s*/)(?<StartDate>(0?[1-9]|[12][0-9]|[3][01])[. -](0?[1-9]|1[0-2])[. -]([0-9]{4}|[0-9]{2})))*
(?:(?:\s*/)(?<EndDate>(0?[1-9]|[12][0-9]|3[01])[. -](0?[1-9]|1[0-2])[. -]([0-9]{4}|[0-9]{2})))*

但是,这将 匹配您的测试字符串,因为字符串中的额外“/testModule”不在您的工作正则表达式中。 您可以修改原始正则表达式以允许在正则表达式的两个部分之间添加额外的斜线吗?

<original regex>
(?:/[^/]+)*   # <-- for the /testModule and any other similar tokens that appear in between
<date regex>

也作为一般观点

  • 你有几个出现(?:(?:regex)*)*。我不确定将外部* 加倍的意义何在,除了让正则表达式解析器无缘无故地比它应该工作的更辛苦(外部(?: )* 在这里是多余的)。
  • (?:/\s*) 没有任何意义,因为你没有对括号做任何事情,所以只做/\s*
  • (?:/client:) 之类的内容相同。如果您没有对它们做任何事情,为什么还要使用非捕获括号。 /client: 可以。
  • (?:regex)* 表示“匹配 0 到无限次出现的 regex”。对于(?:\s*/(?&lt;ClientHelp&gt;help))* 之类的内容,您真的希望这会在您的字符串中无限次出现,还是只会出现一次或根本不出现?考虑将* 替换为?,这意味着“匹配0 或1 次出现”(如果您知道该令牌将出现一次或根本不出现),或者如果您知道,将其替换为(例如){0, 100}令牌将出现最多 100 次(至少 0 次)。这可以提高性能。

所以我建议像这样更改您的正则表达式:

(?<GeneralHelp>^/help\s*)?
/client:
(?<Client>\w*)
(?:\s*/(?<ClientHelp>help))*
(?:\s*/(?<Modules>createHistory)(?:\s*/(?<ModuleHelp>help))*)*
(?:/[^/]+)*
(?:\s*/(?<StartDate>(0?[1-9]|[12][0-9]|[3][01])[. -](0?[1-9]|1[0-2])[. -]([0-9]{4}|[0-9]{2})))*
(?:\s*/(?<EndDate>(0?[1-9]|[12][0-9]|3[01])[. -](0?[1-9]|1[0-2])[. -]([0-9]{4}|[0-9]{2})))*

您可以在regexr 处摆弄您的正则表达式,我在这里用您的正则表达式/测试字符串创建了一个示例。 (编辑:正则表达式中的 似乎已更改为 regexr 中的 ,因此除非您复制/粘贴我直接编写的正则表达式,否则链接将不起作用)

【讨论】:

  • 不错的相当广泛的答案!
  • 谢谢,但它似乎仍然没有捕获日期。
  • 请定义“不起作用”。如果您将此正则表达式与您的测试字符串一起复制/粘贴到正则表达式中,则会按预期捕获组。也许您在实际执行正则表达式时做错了(调用错误的函数,或者没有转义一些特殊字符等)。用更多细节更新原始问题可能会有所帮助。
  • 除了在线正则表达式测试仪没有捕获日期之外,我无法在我的代码中捕获日期,这只会破坏传入的字符串数组参数中的唯一字符串通过控制台应用程序。
  • 如前所述,将帖子中的正则表达式复制粘贴到正则表达式中,它可以工作(您不能使用我直接提供的链接,因为它将 转换为 < 和 >) . “控制台应用程序传入的字符串数组参数中的字符串”一定有错误(所以你使用grepsed或其他什么?你能给出你用来提交的命令/代码吗?正则表达式?)
【解决方案2】:

如果您确定最后两个字段是日期,您可以简单地添加类似

的内容
(?<StartDate>(?:\d+[. -]?){3})/(?<EndDate>.*)$

(甚至 (?&lt;StartDate&gt;[^/]+)/(?&lt;EndDate&gt;.+)$ 如果您的案例都采用相同的模式并且符合您的需求)。

正如 math.coffee 已经指出的,第一个正则表达式可以改进。

【讨论】:

    猜你喜欢
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-13
    • 2019-07-21
    • 1970-01-01
    • 2014-01-02
    • 1970-01-01
    • 2017-02-16
    相关资源
    最近更新 更多