如何用正则数组匹配目标字符串数组?PHP preg_match_all 问题
问题分析与解决方案
首先看你代码的核心问题:
- 内层循环遍历目标数组时,每次都将
$preg_value覆盖为当前元素,循环结束后$preg_value仅保留最后一个目标字符串,导致每个正则表达式都只匹配最后一个目标值。 - 未保存每个正则对应的匹配结果,
$matches会被每次循环覆盖,最终只留下最后一次匹配的结果。 - 金额匹配的正则存在逻辑错误:正则中的
.未转义,会匹配任意字符而非仅小数点;原正则要求必须有小数点后的整数部分,无法匹配165,03这种无小数点的金额格式。
修正方案1:一一对应匹配(正则与目标数组按顺序对应)
如果你的需求是让tax正则匹配目标数组第1项,net_amount匹配第2项,tax_amount匹配第3项,可以用以下代码:
// 修正后的正则数组(转义小数点,调整金额正则兼容无小数点格式) $patterns = [ 'tax' => '/^(\S+\w)/', 'net_amount' => '/^((?:[1-9]\d+|\d)(?:\.(?:[1-9]\d+|\d))?(?:\,\d\d)?)$/', 'tax_amount' => '/^((?:[1-9]\d+|\d)(?:\.(?:[1-9]\d+|\d))?(?:\,\d\d)?)$/' ]; $targets = [ '10,00 % Steuer von', '1.650,31', '165,03' ]; $results = []; $patternKeys = array_keys($patterns); foreach ($patternKeys as $index => $key) { $pattern = $patterns[$key]; $target = $targets[$index] ?? ''; // 用preg_match而非preg_match_all,每个目标字符串只需匹配一次 if (preg_match($pattern, $target, $matches)) { $results[$key] = $matches; } else { $results[$key] = '无匹配结果'; } } // 输出结果 print_r($results);
修正方案2:每个正则匹配所有目标字符串
如果你的需求是让每个正则去匹配目标数组中的所有元素,收集所有符合条件的结果,可以用以下代码:
$patterns = [ 'tax' => '/^(\S+\w)/', 'net_amount' => '/^((?:[1-9]\d+|\d)(?:\.(?:[1-9]\d+|\d))?(?:\,\d\d)?)$/', 'tax_amount' => '/^((?:[1-9]\d+|\d)(?:\.(?:[1-9]\d+|\d))?(?:\,\d\d)?)$/' ]; $targets = [ '10,00 % Steuer von', '1.650,31', '165,03' ]; $results = []; foreach ($patterns as $patternName => $pattern) { $matches = []; foreach ($targets as $targetIndex => $target) { if (preg_match($pattern, $target, $match)) { $matches[$targetIndex] = $match; } } $results[$patternName] = $matches; } // 输出结果 print_r($results);
正则调整说明
针对金额匹配的正则做了两处关键修改:
- 将
.转义为\.,确保仅匹配小数点,避免匹配任意字符。 - 把
(?:[1-9]\d+|\d)\.(?:[1-9]\d+|\d)修改为(?:[1-9]\d+|\d)(?:\.(?:[1-9]\d+|\d))?,让小数点及后续整数部分变为可选,这样既可以匹配1.650,31,也能匹配165,03。
内容的提问来源于stack exchange,提问作者Mirko Babic
相关产品推荐
相关产品推荐

