我正在写一个正则表达式来验证欧元货币字符串。它允许几种不同的格式,因为一些语言环境使用小数点作为千位分隔符,一些使用空格,一些将€放在开头,一些放在最后。以下是我提出的建议:
/^(€ ?)?\-?([1-9]{1,3}( \d{3})*|[1-9]{1,3}(\.\d{3})*|(0|([1-9]\d*)?))(,[0-9]{2})?( ?€)?$/
这适用于以下测试:
有效的:
123 456,78
123.456,78
€6.954.231
€896.954.231
16.954.231€
12 346 954 231€
€10.03
10.03
1,39
,03
0,10
€10567,01
€0,01
€1 234 567,89
€1.234.567,89
无效
1234
€1,1
50#,50个
123,@€
€€500个
0001
€,001
€0.001
12.34,56
123456.123.123456
这样做的一个问题是验证两端带有欧元符号的字符串,例如: €123€。这对于我的目的来说可能是可以接受的,但是有没有办法制作一个紧凑的RegEx,它只允许一端而不是两个,或者我只需要编写一个长度为两倍的字符,首先检查一个有效的字符串,开头是可选的€,然后是一个有效的字符串,结尾有可选的€?
更新
接受的答案中的那个仍然有一些误报。我最终编写了一个函数,它有几个选项来自定义验证器。它是this library中的isCurrency
函数。仍然使用前瞻来避免某些边缘情况,这是回答这个问题的关键。
答案 0 :(得分:3)
预测这将起作用
^(?!€*$)(€ ?(?!.*€)(?=,?\d))?\-?([1-9]{1,3}( \d{3})*|[1-9]{1,3}(\.\d{3})*|(0|([1-9]\d*)?))(,[0-9]{2})?( ?€)?$
请参阅:https://regex101.com/r/aR4xR8/8
@Necreaux值得赞扬,因为它首先指向前瞻!
答案 1 :(得分:2)
根据您的正则表达式引擎,您可以使用否定前瞻来执行此操作。
^€(?!(.*€))
答案 2 :(得分:1)
您可以使用此模式:
^
(?=(.)) # you capture the first character in a lookahead
(?:€[ ]?)?
(?:
[1-9][0-9]{0,2}
(?:
([ .]) [0-9]{3} (?: \2 [0-9]{3})*
|
[0-9]*
)
(?:,[0-9]{2})?
|
0?,[0-9]{2}
)
(?:
[ ]?
(?!\1)€ # you test if the first character is not an €
)?
$
这个想法是捕获第一个字符,并测试它最后是否不一样。
要将其与javascript一起使用,您需要删除格式:
var re = /^(?=(.))(?:€ ?)?(?:[1-9][0-9]{0,2}(?:([ .])[0-9]{3}(?:\2[0-9]{3})*|[0-9]*)(?:,[0-9]{2})?|0?,[0-9]{2})(?: ?(?!\1)€)?$/;
关于这种方式:唯一的兴趣是缺点。如果你想要表演,最好的方法是从字面上写出两种可能性:
var re = /^(?:€ ?(?:[1-9][0-9]{0,2}(?:([ .])[0-9]{3}(?:\1[0-9]{3})*|[0-9]*)(?:,[0-9]{2})?|0?,[0-9]{2})|(?:[1-9][0-9]{0,2}(?:([ .])[0-9]{3}(?:\2[0-9]{3})*|[0-9]*)(?:,[0-9]{2})?|0?,[0-9]{2})(?: ?€)?)$/;
编写它的时间更长,但它会减少正则表达式引擎的工作。
使用支持PCRE等条件子模式的正则表达式引擎,可以这样写:
\A
(€ ?)?
(?:
[1-9][0-9]{0,2}
(?: ([ .]) [0-9]{3} (?:\2[0-9]{3})* | [0-9]*)
(?:,[0-9]{2})?
|
0?,[0-9]{2}
)
(?(1)| ?€)
\z
其中(?(1)| ?€)
是 if..then..else :(?(condition)true|false)
,用于检查是否定义了捕获组1。
答案 3 :(得分:0)
您可以将您的正则表达式分成两方,并将它们与“|”组合。 一个用于收取€和另一个用于€的结尾。
/(^(€ ?)?\-?([1-9]{1,3}( \d{3})*|[1-9]{1,3}(\.\d{3})*|(0|([1-9]\d*)?))(,[0-9]{2})?$)|(^\-?([1-9]{1,3}( \d{3})*|[1-9]{1,3}(\.\d{3})*|(0|([1-9]\d*)?))(,[0-9]{2})?( ?€)?$)/
修改强>
我错过了你的最后一句话。 我认为最简单的方法是将正则表达式编写两次。答案 4 :(得分:0)
这是我能够来的最接近的人。它使用否定前瞻来确保字符串不以欧元符号€
开头和结尾:
^(?!€.*€$)€?\s*(0|[1-9][0-9]{0,2})?([. ]?[0-9]{3})*(,[0-9]{2})?\s*€?$
See Regex 101 Demo here有完整的解释和示例。正如您所看到的那样,它会通过您的所有测试,但它会让一些不好的测试通过。我确定数字部分可以调整,以便它适合您。确保没有两个欧元符号的部分就是这样:
^(?!€.*€$)€?\s*<digit validation goes here>\s*€?$
否定前瞻确保字符串不以欧元符号开头和结尾,然后在开始时检查可选的欧元符号,后跟任意数量的空格,验证数字,然后检查任意数量的#空格和最后的欧元符号。