如何用PHP preg_replace转换Apple Maps坐标为通用格式?
解决方案
你的原有正则存在几个核心问题:
- 未覆盖纬度(0-90)和经度(0-180)的完整合法范围(比如无法匹配
90,0000° N这类极值) - 替换时没有将德语格式的逗号小数点转换为通用的点格式
- 未处理方向对应的正负符号(比如S纬度、W经度需要转为负数)
以下是修正后的实现方案:
正则表达式优化
使用更精准的正则匹配坐标格式,同时支持逗号/点作为小数点,匹配N/S/E/O/W方向标识:
$regex = '/^([1-8]?\d(?:[.,]\d+)?|90(?:[.,]0+)?)\s*°\s*(N|S)\s*,\s*((?:180(?:[.,]0+)?|(?:1[0-7]\d|[1-9]?\d)(?:[.,]\d+)?))\s*°\s*(E|O|W)$/i';
正则各部分说明:
([1-8]?\d(?:[.,]\d+)?|90(?:[.,]0+)?):匹配合法纬度数值(0-90,支持逗号/点小数点)\s*°\s*(N|S):匹配纬度方向标识(忽略前后空格,不区分大小写)\s*,\s*:匹配坐标间的逗号分隔符(忽略前后空格)((?:180(?:[.,]0+)?|(?:1[0-7]\d|[1-9]?\d)(?:[.,]\d+)?)):匹配合法经度数值(0-180,支持逗号/点小数点)\s*°\s*(E|O|W):匹配经度方向标识(O对应德语的东,等同于E)
替换逻辑实现
由于需要同时处理小数点转换和方向正负,使用preg_replace_callback而非直接preg_replace,可以灵活处理每个匹配项:
$input = "38,89016° N, 1,22427° O"; // 德语格式示例 // $input = "38.89016° N, 1.22427° E"; // 英语格式示例 $regex = '/^([1-8]?\d(?:[.,]\d+)?|90(?:[.,]0+)?)\s*°\s*(N|S)\s*,\s*((?:180(?:[.,]0+)?|(?:1[0-7]\d|[1-9]?\d)(?:[.,]\d+)?))\s*°\s*(E|O|W)$/i'; $output = preg_replace_callback($regex, function($matches) { // 处理纬度:替换逗号为点,根据方向添加正负 $lat = str_replace(',', '.', $matches[1]); $lat = $matches[2] === 'S' ? "-$lat" : $lat; // 处理经度:替换逗号为点,O等同于E,W则加负号 $lng = str_replace(',', '.', $matches[3]); $lng = in_array(strtoupper($matches[4]), ['W']) ? "-$lng" : $lng; return "$lat, $lng"; }, $input); // 输出结果:38.89016, 1.22427 echo $output;
关键改进点
- 精准匹配范围:确保仅匹配合法的坐标格式,排除地址等非坐标内容
- 小数点统一:将德语格式的逗号小数点转换为通用的点格式
- 方向正负处理:自动将S(南纬)、W(西经)转换为负数,符合通用坐标规范
- 大小写兼容:通过
/i修饰符支持大小写不敏感的方向标识匹配
如果不需要处理正负符号(仅保留原数值的小数点转换),可以简化回调逻辑:
$output = preg_replace_callback($regex, function($matches) { $lat = str_replace(',', '.', $matches[1]); $lng = str_replace(',', '.', $matches[3]); return "$lat, $lng"; }, $input);
内容的提问来源于stack exchange,提问作者Tim Nikischin
相关产品推荐
相关产品推荐

