正则表达式查找美元金额但不匹配IP地址

时间:2017-10-30 19:02:11

标签: php regex

我的文本部分可能包含美元金额,可能会或可能不会附加美元符号和IP地址。我需要一个正则表达式来识别美元金额但不匹配IP地址的部分。

例如,如果文字是:

12.34 56.78.90.12 34.56

我的首发尝试是:

([1-9]\d*\.\d{2})

这是我想要匹配的内容,但它匹配部分IP地址。然后我尝试了:

[^\.]([1-9]\d*\.\d{2})[^\.]

但几乎在所有情况下情况都更糟。

正则表达式需要匹配“12.34”和“34.56”,而不是“56.78”或“90.12”。任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:2)

另一种与REGEX不同的方法,假设每个元素(dollar amount or ip address)之间有一个空格,就是按空格分解元素,得到只有一个点的元素列表。

$text = "12.34 56.78.90.12 34.56";

$dollars_amt = array_filter(explode(' ', $text), function($s) {
    if (substr_count($s, '.') == 1) {
        return $s;
    }
});

print_r($dollars_amt);

结果:

Array ( [0] => 12.34 [2] => 34.56 )

答案 1 :(得分:1)

使用lookaround assertionsword boundary anchors确保您的匹配项周围没有任何点:

(?<!\.)\b[1-9]\d*\.\d{2}\b(?!\.)

测试live on regex101.com

答案 2 :(得分:1)

(?<=^|[^\d.])\d+\.\d+(?=[^\d.]|$)

它基本上试图匹配这个:

\d+\.\d+

当字符串的开头(^)或不是数字或点([^\d.])的字母后面和字符串的末尾($)或者不是数字或点([^\d.])的东西就在它之后。

Try it here.

答案 3 :(得分:0)

使用不合格的(*SKIP)(*FAIL)模式的速度将是目前发布的其他正则表达式模式的两倍以上。

/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(*SKIP)(*FAIL)|\$?[1-9]\d*\.\d{2}/
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- IP address   ^^^^^^^^^^^^^^^- currency amount

在尝试将您的货币值与可选的领先美元符号匹配之前,这将首先查找和取消IP地址。此模式允许您在不使用捕获组的情况下匹配您的美元金额 - 这将提高性能并减少来自preg_match_all()

的输出数组膨胀

Pattern Demo Link

代码:(PHP Demo

$string='12.34 56.78.90.12 34.56 156.8.90.2 $99999.99';
var_export(preg_match_all('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(*SKIP)(*FAIL)|\$?[1-9]\d*\.\d{2}/',$string,$out)?$out[0]:'fail');

输出:

array (
  0 => '12.34',
  1 => '34.56',
  2 => '$99999.99',
)