正则表达式用于在给定字符串之前或之后放置的数字

时间:2018-09-20 13:29:51

标签: regex

我有一组像这样的字符串:

[
  "ERDF : EUR 2.7 million",
  "ERDF : EUR 961 000",
  "ERDF: 7 305 000 DKR (+/- EUR    974 000) ",
  "FEOGA: 40 826 EUR",
  "49 % of eligible costs",
  "ERDF contribution: 64%",
  "FEDER (Objectif 5b 1994-1996) 60 979 euros (400 000 FRF)",
  "FEDER, Objectif 2, 1994 - 1999: 1 116 000 EUR",
  "EUR 8.000.000",
  "EUR 7.200.000",
  "EUR 4.200.000",
  "4.2 million euros",
  "EUR 0.2 million",
  "EUR 0.6 million",
  "FEDER: 830 842 euros (5 450 000 FRF)",
  "EUR  7,220,000,000",
  "DKR 1 220 000 + DKR 1 380 000 ",
  "GBP 150 000" ]

regex101.com上在线

我想捕获带有eur*作为前缀或后缀的数字(如果存在,则带有'million')。以下情况应与表达式匹配

10 million euros
EURO 5.000
EUR 100

仅当eur*在数字前

,我当前的正则表达式才有效
/(\beur[a-z]*|€)+[\s\d\,\.|million]*\b/gi

2 个答案:

答案 0 :(得分:1)

基本答案

我会推荐类似的东西

/(?:eur\w*|€)?\s*([0-9\., ]+)\s*(million)?\s*(?:eur\w*|€)?/i

这会将数字和“百万”识别为两个单独的捕获组,并匹配您给定的每个示例:

  • EUR 7.200.000->组1 = 7.200.000
  • euro 4 000->组1 = 4 000
  • EUR 0.2 million->组1 = 0.2,组2 = million
  • Main project: 300 000 EUR->组1 = 300 000
  • 1998: 43.000.000 euros->组1 = 43.000.000

这里是您可以使用的live example at Regex101正则表达式。

更完整的答案

现在,也就是说,这个答案与原始请求完全不同,因为它也匹配裸机号码。如果您需要一个绝对仅匹配eur前后的数字,则需要复制和分割正则表达式,如下所示:

/(?:eur\w*|€)\s*([0-9\., ]+)\s*(million)?|([0-9\., ]+)\s*(million)?\s*(?:eur\w*|€)/i

这正确地捕获了您上面所有的原始示例,但不会捕获裸露的数字。

我也有这种形式的live example on Regex101

以下是与您提供的the extended dataset相匹配的正则表达式;请注意,它与法郎,百分比,英镑或其他任何不希望有的值都不匹配,但是正确提取了每一欧元。

超越问题

如@blhsing所建议的那样,在包含\b字边界方面可能会有一定的价值,以使该Grandeur 100之类的东西匹配。这些字边界字符在正则表达式中的eur之前:

/(?:\beur\w*|€)\s*([0-9\., ]+)\s*(million)?|([0-9\., ]+)\s*(million)?\s*(?:\beur\w*|€)/i

奇怪的特殊情况

Radu问为什么上面的示例与以下示例不正确匹配:

ERDF : EUR 2.7 million

或者,更具体地说,他想知道为什么它只捕获。答案是正则表达式贪婪:它们从左到右捕获,并尽可能快地捕获。因此,正则表达式引擎一看到EUR,就可以正确捕获那个作为答案,因为我们已经允许为“数字”!

解决此问题的方法是要求每个“数字”至少以实际的数字开头-以.,开头不应该被允许。我们可以这样扩展数字部分来做到这一点:

  • [0-9\., ]+(这些数字字符中的一个或多个)
    • 成为-> [0-9][0-9\., ]*(仅 一个数字,然后是零个或多个其他字符)

因此,扩展的正则表达式不会因为过于贪婪而错误地捕捉到Radu的另一个示例(并且包括单词的边界),这看起来有点丑陋:

/(?:\beur\w*|€)\s*([0-9][0-9\., ]*)\s*(million)?|([0-9][0-9\., ]*)\s*(million)?\s*(?:\beur\w*|€)/i

正则表达式学习

此正则表达式如何工作?它使用了一些原始的基本部分:

  • 首先,它广泛使用(?:...),这是一个不可捕获的组:(?:...)就像括号一样,将事物组合在一起具有优先权,但是实际上并没有捕获其内容作为输出的一部分。
  • 此正则表达式的某些版本还使某些内容可以使用?可选。

基于这些知识,我们可以将整个模式(在下面再次复制)分解为逻辑块:

/(?:eur\w*|€)\s*([0-9\., ]+)\s*(million)?|([0-9\., ]+)\s*(million)?\s*(?:eur\w*|€)/i
  • 在左侧:
    • (?:eur\w*|€)首先匹配eur...部分。
    • 然后\s*匹配可选的空格。
    • 然后([0-9\., ]+)捕获数字。
    • 还有更多可选的空格:\s*
    • 最后,我们捕获了一个可选的“百万”:(million)?
  • 在右侧:
    • 首先,我们匹配并捕获数字:([0-9\., ]+)
    • 然后\s*匹配一些可选的空格。
    • 然后我们捕获一个可选的“百万”:(million)?
    • 然后是一些可选的空白:\s*
    • 最后,我们确保其后跟eur...(?:eur\w*|€)

答案 1 :(得分:0)

您也可以尝试((?=[\w\s\d\.]+eur)|(?=[\w\s\d\.]+EUR))(eur(os)?|EUR(OS)?|million|\s|\d|\.)+?(?=$|\(|\))

https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-updatestats-transact-sql?view=sql-server-2017