含HTML的数字分组格式化:正则表达式问题求助
解决方案
方法一:通过数字偏移量分步分割(推荐)
这种方法先提取所有数字在原字符串中的位置,再按位置直接分割,完全忽略中间的HTML代码,逻辑清晰且不易出错:
$inputStr = "你的目标字符串,包含任意HTML和数字,比如:前缀<b>1</b>2<div>3</div>45<em>6789</em>01234后缀内容"; // 提取所有数字及其在字符串中的偏移量 preg_match_all('/\d/', $inputStr, $digitMatches, PREG_OFFSET_CAPTURE); $digitCount = count($digitMatches[0]); // 先检查数字数量是否满足要求 if ($digitCount < 13) { die("错误:字符串中的数字数量不足13个"); } // 提取对应数字的偏移量(数组索引从0开始,第3个数字对应索引2,以此类推) $offsets = [ 2 => $digitMatches[0][2][1], // 第3个数字的偏移量 4 => $digitMatches[0][4][1], // 第5个数字的偏移量 6 => $digitMatches[0][6][1], // 第7个数字的偏移量 10 => $digitMatches[0][10][1], // 第11个数字的偏移量 12 => $digitMatches[0][12][1] // 第13个数字的偏移量 ]; // 按偏移量分割字符串为指定的6组 $groups = [ substr($inputStr, 0, $offsets[2]), // 组1:第3个数字前的所有文本 substr($inputStr, $offsets[2], $offsets[4] - $offsets[2]), // 组2:第3至第5个数字前的文本 substr($inputStr, $offsets[4], $offsets[6] - $offsets[4]), // 组3:第5至第7个数字前的文本 substr($inputStr, $offsets[6], $offsets[10] - $offsets[6]), // 组4:第7至第11个数字前的文本 substr($inputStr, $offsets[10], $offsets[12] - $offsets[10]), // 组5:第11至第13个数字前的文本 substr($inputStr, $offsets[12]) // 组6:第13个数字到末尾的文本 ]; // 输出结果示例 foreach ($groups as $idx => $content) { echo "组" . ($idx + 1) . ": " . htmlspecialchars($content) . "\n"; }
方法二:使用正则表达式一次性捕获分组
如果偏好正则写法,可以用带有正向预查的正则来精准定位数字位置,忽略中间的HTML:
$inputStr = "你的目标字符串,包含任意HTML和数字,比如:前缀<b>1</b>2<div>3</div>45<em>6789</em>01234后缀内容"; // 检查数字数量 preg_match_all('/\d/', $inputStr, $digitMatches); if (count($digitMatches[0]) < 13) { die("错误:字符串中的数字数量不足13个"); } // 构建正则模式,使用正向预查定位目标数字位置 $pattern = '/^ (.*?) # 组1:开头到第3个数字前 (?=(?:\D*\d){2}\D*\d) # 预查:匹配前2个数字(含中间非数字/HTML)+ 第3个数字 (\D*\d.*?) # 组2:第3个数字到第5个数字前 (?=(?:\D*\d){1}\D*\d) # 预查:匹配第4个数字(含中间非数字/HTML)+ 第5个数字 (\D*\d.*?) # 组3:第5个数字到第7个数字前 (?=(?:\D*\d){1}\D*\d) # 预查:匹配第6个数字(含中间非数字/HTML)+ 第7个数字 (\D*\d.*?) # 组4:第7个数字到第11个数字前 (?=(?:\D*\d){3}\D*\d) # 预查:匹配第8-10个数字(含中间非数字/HTML)+ 第11个数字 (\D*\d.*?) # 组5:第11个数字到第13个数字前 (?=(?:\D*\d){1}\D*\d) # 预查:匹配第12个数字(含中间非数字/HTML)+ 第13个数字 (\D*\d.*)$ # 组6:第13个数字到末尾 /sx'; preg_match($pattern, $inputStr, $matches); array_shift($matches); // 移除整个匹配的完整字符串,保留6个分组 // 输出结果示例 foreach ($matches as $idx => $content) { echo "组" . ($idx + 1) . ": " . htmlspecialchars($content) . "\n"; }
关键说明
- 两种方法都先检查数字数量,避免因数字不足导致的错误
- 方法一中的
PREG_OFFSET_CAPTURE标记用于获取每个数字在原字符串中的精确位置,确保分割准确 - 方法二中的
\D匹配任意非数字字符(包括HTML标签、空格、符号等),(?:\D*\d)用于跳过“任意非数字+一个数字”的组合,精准定位目标数字的位置 - 正则中的
s修饰符让.匹配换行符,x修饰符允许正则中添加空白,提升可读性
内容的提问来源于stack exchange,提问作者Anrik
相关产品推荐
相关产品推荐

