使用preg_replace正则移除字符串开头2位字符 仅保留NW/SE等方向标识
问题原因
你当前的写法触发了preg_replace的数组规则遍历逻辑:函数会按顺序对输入字符串执行数组内的每一条替换规则,而非匹配到第一条符合的规则就停止。
所以当你前四条规则把方向前缀转成「大写双字母+空格」的格式后,第五条规则/^[A-Za-z]{2}\s/会再次匹配到刚生成的方向前缀,直接将其清空。
解决方案
方案1:修改第五条规则加负向预查(改造成本最低)
只需要给第五条匹配规则加个负向前置断言,排除方向组合的匹配即可,其他代码完全不用动:
// 原第五条规则替换为这条,意思是:仅匹配开头两个字母不是NS+EW组合的情况 $cleanpattern[] = '/^(?![NnSs][EeWw])[A-Za-z]{2}\s/';
如果要兼容单字母方向的需求,只要在规则数组前加4条单字母匹配规则即可,和双字母方向规则逻辑一致:
// 加在方向双字母规则之前即可 $cleanpattern[] = '/^[Nn]\s/'; $cleanpattern[] = '/^[Ss]\s/'; $cleanpattern[] = '/^[Ee]\s/'; $cleanpattern[] = '/^[Ww]\s/'; $replacementpattern[] = 'N '; $replacementpattern[] = 'S '; $replacementpattern[] = 'E '; $replacementpattern[] = 'W ';
单字母规则不会和第五条双字母规则冲突,无需额外调整。
方案2:用preg_replace_callback一次性处理(逻辑更简洁,性能更好)
直接用单次正则匹配+回调处理所有分支,无需维护多组规则数组,也不会出现多轮替换冲突的问题:
$town = preg_replace_callback('/^(?<dir>[NnSsEeWw]{1,2})\s|^[A-Za-z]{2}\s/', function($match) { // 匹配到方向前缀,转大写后加空格返回 if (isset($match['dir'])) { return strtoupper($match['dir']) . ' '; } // 匹配到普通双字母前缀,返回空直接清除 return ''; }, $town);
这个写法天然兼容单/双字母方向前缀的需求,也不会出现多轮替换的冲突问题。
内容的提问来源于stack exchange,提问作者jeffkee
相关产品推荐
相关产品推荐

