如何解决€25.99 vs 25,99€preg_match问题?

时间:2011-08-04 19:06:45

标签: php regex euro

如果我有这些字符串:

$string1 = "This book costs €25.99 in our shop."

在另一边

$string2 = "This book costs 25,99€ in our shop."

如何使用 preg_match 获得“€25.99”或“25,99€”?代码将如何?

请注意,有两种方式可以写入欧元符号。欧盟的正确方法是在25,99€之后写下符号并使用逗号作为desimal分离器即可。然而,很多美国人坚持使用美元方式(25.99欧元)和点数作为空间分隔符

如何检查这两种情况并以最干净,最有效的方式获取带符号的值?

3 个答案:

答案 0 :(得分:4)

这是原始正则表达式:€\d+(?:[,.]\d+)?|\d+(?:[,.]\d+)?€

preg_match ( "/€\d+(?:[,.]\d+)?|\d+(?:[,.]\d+)?€/" , $string1, $matches)

如果要考虑欧元和值之间的可选空格,请使用:

preg_match ( "/€ ?\d+(?:[,.]\d+)?|\d+(?:[,.]\d+)? ?€/" , $string1, $matches)

答案 1 :(得分:2)

agent-j 的模式在正确的轨道上,但我会做一些稍微限制的事情:

/€\d+(:?[.,]\d{2})?|\d+(:?[.,]\d{2})?€/

唯一的区别是小数部分限制为2个位置(如果存在)。我认为你不想允许像99,999€这样的东西,特别是因为如果用美国风格写的话,这可能意味着“99000,999欧元”。

我认为你在提及最干净,最有效的方式时所想要的是,当你看到它时,上述模式似乎很笨拙和多余。它基本上是重复两次的\d+(:?[.,]\d{2})?部分,其中符号切换边。这个感觉错了,但事实并非如此。如果不引入同样多的复杂性,你就无法真正解决它。即使你尝试用花哨的外观来解决它,它也会看起来像这样:

/^(?=.*€)€?\d+(:?[.,]\d{2})?((?<!€.*)€)?$/

显然不是一种改进。有时最明显的解决方案是最好的解决方案,即使它让你感觉很脏。

注意:如果你真的对它感到疯狂,你可以尝试一种变化(谨慎:未经测试,我在一段时间内没有做太多PHP):

$inner = "(:?\d{1,3}(?:([.,])\d{3})*(?:(?!\1)[.,]\d{2})?|\d*(?:[.,]\d{2})?)";

用法:

preg_match ( "/€" . $inner . "|" . $inner . "€/", $string1, $matches)

那也应该接受像99,999.99这样的东西; 999999,99; 9.999.999,99; 0.99;等

答案 2 :(得分:0)

检查两种情况:

/([$€]?[\d,]+[$€]?)/

?使[$€]可选(字面意思为'0或1的......'),因此您必须检查退化情况,其中只有一个没有货币符号的裸号。