正则提取user-agent关键信息的核心是判得准、顺序对、抓得稳:按edg→firefox→chrome→safari→ie/edge legacy优先级匹配浏览器,os识别需归一化分隔符,版本提取须用专属正则避免空格分割与贪婪匹配,轻量封装为可扩展调试的函数。

直接用正则提取 User-Agent 的关键信息,核心不在“写得多”,而在“判得准、顺序对、抓得稳”。UA 字符串没有统一标准,同一浏览器在不同平台、版本甚至隐私模式下格式都可能变化,硬套一个通用正则很容易漏判或误判。高效的关键是建立清晰的匹配优先级、针对每个浏览器特征精准捕获、并统一处理版本号格式。
按优先级顺序匹配浏览器标识
多个浏览器关键词常共存于一条 UA 中(比如 Chromium 内核的 Edge 同时含 Edg/ 和 Chrome/),必须严格按优先级从前到后逐一尝试,命中即停:
- 新版 Edge:先匹配
Edg\/([\d.]+)—— 注意是 Edg,不是 Edge;若放在 Chrome 后面,就会被 Chrome 正则提前截走 - Firefox:匹配
Firefox\/([\d.]+),独立性强,无干扰项 - Chrome 及其变体(含 Headless):用
Chrome\/([\d.]+),但需确保前面已排除 Edge - Safari:必须加防护条件——
Safari\/存在且Chrome不存在,再从Version\/([\d.]+)提取版本(Safari 不用 Chrome/ 格式) - IE/Edge Legacy:用
Trident.*?rv:([\d.]+)|MSIE ([\d.]+),注意捕获组索引可能偏移,建议用命名组或检查 match[1] 或 match[2]
操作系统识别要兼顾主流与格式归一
OS 信息集中在 UA 括号内,但版本分隔符不统一(macOS 用下划线,Windows 用点,Android 用点,iOS 常无显式版本号):
- Windows:匹配
Windows NT (\d+\.\d+),直接获取主次版本 - macOS:用
Mac OS X (\d+_\d+[_\d]*),提取后把下划线替换成点,如10_15_7 → 10.15.7 - iOS:靠设备关键词
iPhone|iPad|iPod判定,再结合CPU OS (\d+_\d+)或OS (\d+_\d+)提取版本 - Android:匹配
Android (\d+\.\d+),部分旧 UA 可能只写Android (\d),可放宽为Android ([\d.]+) - Linux / ChromeOS:用
Linux或CrOS粗略识别,无需强求版本
版本号提取别依赖空格分割
UA 中版本号紧贴标识符,前后未必有空格,硬切空格或空格+斜杠组合极易出错:
- 错误写法:
explode(' ', $ua)[1]—— Chrome/125.0.6422.113 后面可能紧跟 AppleWebKit,根本没空格 - 正确做法:对每个浏览器用专属正则,如
/Chrome\/([\d.]+)/i、/Version\/([\d.]+)/i、/Edg\/([\d.]+)/i - 避免贪婪匹配:比如
/Version\/(.*)/会一路吃到结尾,应限定为/Version\/([\d.]+)/或更稳妥的/Version\/([\d.]{1,8})/
轻量封装,便于扩展和调试
不推荐堆砌长正则或单函数大杂烩。建议拆成小函数,每个只负责一类识别,并支持 fallback:
- 定义
detectBrowser($ua),返回数组['name' => 'Chrome', 'version' => '125.0'] - 定义
detectOS($ua),统一返回['name' => 'macOS', 'version' => '14.5'] - 所有正则启用
i修饰符,忽略大小写 - 加入日志或 debug 模式:当匹配失败时,输出未识别的 UA 片段,方便后续补充规则











