PHP正则匹配3-4列含空格可选列的网络节点数据问题
PHP环境下解析多空格分隔节点数据文件的正则方案
场景说明
在PHP环境中解析网络节点数据文件,每行最多包含4列,第4列为可选字段,列定义如下:
<Node name> <Operating System> <Description> <SSL info>
列分隔规则:列与列之间通过2个及以上连续空格分隔,单个空格属于列内内容。
测试数据样例:
SIG.SND.SERV ZOS A Big client (MF LPAR PROD) ADC1 ZOS AMEX SSL ADEPTRA.GB1.PROD LINUX BANK OF SOMEWHERE TLS ADEPTRA.GB2.CQA LINUX BANK OF SOMEWHERE TLS AIX.EG3C UNIX BARCLAYS S+ AIX.EG3P UNIX BARCLAYS S+ ADEPTRA.GB2.CQA LINUX FICO (ADEPTRA) LTD TLS AIX.RMWDEV1 UNIX FDCS AIX.RMWPROD1 UNIX FDCS AIX-EFXWRWCK01 UNIX EQUIFAX EUROPE ANB-DRC-CDFDI NT ARAB NATIONAL BANK (ANB) SSL
已知匹配难点
- 第3列Description字段可包含任意数量空格,单词间允许存在多个连续空格
- 第4列SSL info为可选字段,整行可能缺失该列
- 此前尝试的正则均存在适配缺陷:
- 第一版正则
(\S+)\s+(\S+)\s+(\S.+?\S)\s+(\S.+)?:仅第4列存在时可正常匹配,第4列缺失时匹配失败 - 第二版正则
(\S+)\s{2,} (\S+)\s{2,} (\S.+\S)(\s{2,})? ?(\S.+)?:第4列缺失时可完成匹配,但会将第4列内容错误合并到第3列 - 第三版正则
(\S.+?\S)[\s{2}|$]:字符类规则逻辑错误,无法正确拆分各列边界
- 第一版正则
可用正则及实现
正则表达式
兼容行首行尾空白、第4列可选场景的正则如下:
/^\s*(\S+)\s{2,}(\S+)\s{2,}(.*?\S)(?:\s{2,}(\S+))?\s*$/
分组对应关系
- 分组1:匹配Node name节点名称
- 分组2:匹配Operating System操作系统字段
- 分组3:匹配Description描述字段,完整保留字段内部的单/多空格,自动剔除字段尾部冗余空格
- 分组4:可选匹配项,对应SSL info字段,无该列时返回空值
PHP调用示例
// 逐行读取文件后,单行走正则匹配即可 $line = " SIG.SND.SERV ZOS A Big client (MF LPAR PROD)"; preg_match('/^\s*(\S+)\s{2,}(\S+)\s{2,}(.*?\S)(?:\s{2,}(\S+))?\s*$/', trim($line), $matches); // 剔除全量匹配的第0项,剩余即为4列内容 $columns = array_slice($matches, 1);
匹配效果
对提供的11行测试数据可实现100%正确拆分:
- 无第4列的行:第4分组返回空,第3列描述完整保留内部空格格式
- 有第4列的行:SSL字段被正确拆分到第4分组,不会与第3列内容合并
内容的提问来源于stack exchange,提问作者Steve Ives
相关产品推荐
相关产品推荐

