GBP / USD / EUR

时间:2017-11-14 11:48:19

标签: python regex python-3.5 currency

需要一些帮助才能创建满足以下规则的正则表达式。任何建议都将不胜感激。

(1a。)可选择以下列开头:     £,$,€

1b。货币值必须以一到三位开头

2a。逗号之前:必须有一到三位

2b。逗号后:必须有三位数

2C 即可。小数点后:只能有数字

3a。货币值必须以一位或多位数结尾

[3b。] 值后面可能是:     tn / Tn /万亿/万亿,百万/亿/十亿/亿,百万/百万。

(3c。)可选择以:     p / P / Pence /便士,c / C /美分/美分,欧元/欧元(s)/欧元,美元/美元,英镑/英镑。

规则1a和3c是互斥的,但必须使用其中一个:

$1 dollar ✘
1 ✘
$1 ✓
1 dollar ✓

规则3b可以与规则1a或3c一起使用,但不需要使用:

$1 trillion ✓
1 trillion dollars ✓
$1 ✓

规则2a / 2b可以使用零次或多次:

$1 ✓
$1,000,000,000,000 ✓

规则2c只能使用一次或零次:

$1 ✓
$1.000 ✓

预期结果:

$1 dollar ✘
1 ✘
$1,00000.000,000 ✘
1,000.00 ✘

$1 ✓
1 dollar ✓
$1 trillion ✓
1 trillion dollars ✓
$1,000,000,000,000 ✓
$1.000 ✓
$1,000,000,000,000.000000 ✓

这是我到目前为止所拥有的:

[£€$]?[0-9]+[,.]?[0-9][pcm][ euros| euro]*

2 个答案:

答案 0 :(得分:1)

以下正则表达式并不依赖于单独行上的值,但也会从句子中抓取它们。

它还假设单位"美分","美元"和"磅"可以是单数。

另外,它允许单词和数字之间有无限的空格,并且数字和后面的值字或单元之间也有 no 空格。

<强>解释

以下是正则表达式的基本结构,其子表达式由两个@ s包围的值表示:

(@Prefix@)?(?=(@Value@)(\s*@Postfix@)?)(?(1)\2(?!\3)|(?<!@Prefix@)\2\3)
|________|    |_______||____________|  |______________________________|
    |             |           |                       |
 Group 1       Group 2    Group 3          Prefix-Postfix Selector

组1可选地匹配前缀。

组2和组3在前瞻中被捕获,因此当执行Prefix-Postfix Selector时,只有组1是整体匹配的一部分。

Prefix-Postfix Selector是一个条件语句,它执行以下操作:

  • 如果第1组(Prefix)匹配,则将第2组(Value)添加到整体匹配中,如果其后没有第3组(Postfix)。

  • 如果未匹配Prefix,则将总体匹配设置为Value,然后设置为Postfix,前提是Prefix之前没有Value

子表达式相当不言自明。 \b确保整个单词匹配。同样,数字后面的负前瞻(?![\d.,])可确保没有任何数字,逗号和小数点。

@prefix @:

[£€$]

@Value @:

\d{1,3}(?:,\d{3})*(?:\.\d+)?(?![\d.,])(?:\s*(?:[tTbB]n|m|(?:[tT]r|[bBmM])illion)\b)?
|_____||_________||________||        ||                                            |
|__________________________||________||____________________________________________|
             |                   |                          |
   Number, e.g. 12,345.6         |    [[Whitespace] + Value Word, e.g. Tn or Billion]
                                 |
           Makes sure "1000" is not matched, for example

@Postfix @:

\s*(?:[pP](?:ence)?|[cC](?:ents?)?|€|[eE]uros?|[dD]ollars?|[pP]ounds?)\b

<强>解决方案:

用子表达式替换占位符会导致这个完整的正则表达式:

([£€$])?(?=(\d{1,3}(?:,\d{3})*(?:\.\d+)?(?![\d.,])(?:\s*(?:[tTbB]n|m|(?:[tT]r|[bBmM])illion)\b)?)(\s*(?:[pP](?:ence)?|[cC](?:ents?)?|€|[eE]uros?|[dD]ollars?|[pP]ounds?)\b)?)(?(1)\2(?!\3)|(?<![£€$])\2\3)

Demo

<强>注意事项:

  • 像&#34; $ 1&#34;出现在句子后跟逗号或句号不匹配。 (例如,句子$2中仅匹配This sentence is worth $1, $2 or $3.。)

  • 允许使用逗号和/或小数点 作为值字的数字组成的值,例如&#34; 1,000,000,000&#34;。

答案 1 :(得分:0)

要进行互斥管理,您可以使用货币符号分组和普通货币名称的测试组:

^([$£€])?\d{1,3}(?:,\d{3})*(?:\.\d+)?\s?(?:(?:[BMbm]|[Tt]r)(?:illion)?)?(?(1)|\s(?:(?:[Dd]ollar|[Pp]ound|[Ee]uro|[Cc]ent)s?|€|[Pp]ence))$

Demo