我的文本部分可能包含美元金额,可能会或可能不会附加美元符号和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”。任何帮助将不胜感激。
答案 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 assertions和word boundary anchors确保您的匹配项周围没有任何点:
(?<!\.)\b[1-9]\d*\.\d{2}\b(?!\.)
答案 2 :(得分:1)
(?<=^|[^\d.])\d+\.\d+(?=[^\d.]|$)
它基本上试图匹配这个:
\d+\.\d+
当字符串的开头(^
)或不是数字或点([^\d.]
)的字母后面和字符串的末尾($
)或者不是数字或点([^\d.]
)的东西就在它之后。
答案 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()
代码:(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',
)