从多行字符串中移除含非数字的括号内容时正则表达式误删整行问题排查
解决PHP正则删除括号内非数字内容的问题
看起来你之前的思路是匹配整行符合要求的内容,但这个逻辑存在明显问题:只要行里存在任何不符合的括号对(比如( MONDAY)),整行就不会被preg_match_all捕获到,最后自然就被删掉了。我们换个更直接的思路:直接替换掉所有包含非数字内容的括号对,而不是筛选整行。
修正方案
核心思路
用preg_replace精准定位并删除那些括号内包含非数字字符(字母、空格等)的括号对,保留纯数字的括号内容。
代码实现
$str = '# (1437) # {19} (917) (1437) # {19} (1437) [1449] [2474] [2098] [1351] [508] [969]( MONDAY) [sunday]'; // 正则:匹配括号内包含非数字非空格的括号对 $re = '/\([^)]*[^\d\s][^)]*\)|\{[^}]*[^\d\s][^}]*\}|\[[^\]]*[^\d\s][^\]]*\]/'; $cleanedStr = preg_replace($re, '', $str); // 如果你不需要去重(看你的期望输出是保留重复内容),直接输出即可 echo trim($cleanedStr); // 如果你确实需要去重(和你原代码逻辑一致),可以加上这一步: // $parts = preg_split('/\s+/', trim($cleanedStr)); // $uniqueParts = array_unique($parts); // echo implode(' ', $uniqueParts);
正则解释
这个正则分三部分,分别对应()、{}、[]三种括号:
\([^)]*[^\d\s][^)]*\):匹配()包裹的内容,其中至少有一个非数字且非空格的字符(比如字母、符号)\{[^}]*[^\d\s][^}]*\}:同上,针对{}\[[^\]]*[^\d\s][^\]]*\]:同上,针对[]
扩展:删除空括号/仅含空格的括号
如果括号内只有空格(比如( ))你也想删除,可以把正则里的[^\d\s]改成[^\d]:
$re = '/\([^)]*[^\d][^)]*\)|\{[^}]*[^\d][^}]*\}|\[[^\]]*[^\d][^\]]*\]/';
这样连空括号或者仅含空格的括号都会被一并删除。
为什么原代码失效?
你原正则/^(#\h*)((\[\d+]|\{\d+}|\(\d+\))(?:\h+(?3))*)$/m是匹配整行完全由#开头+纯数字括号组成的内容。只要行里有任何不符合的部分(比如( MONDAY)),整行就不会被匹配,preg_match_all拿不到数据,最后自然就被过滤掉了。
内容的提问来源于stack exchange,提问作者www.friend0.in
相关产品推荐
相关产品推荐

