Angular表单IP地址正则验证出现误判问题排查
IP地址正则验证误判问题分析与解决
在实现IP地址输入验证时,遇到了奇怪的误判情况:
- 有效IP
1.1.1.1和无效IP1...的验证结果正确 - 无效IP
123.123却被误判为有效
测试代码
HTML代码
<form [formGroup]="form"> <div> <input type="text" formControlName="ipValid" [pattern]="ipRegex" /> <span *ngIf="form.hasError('pattern', ['ipValid'])">Pattern error</span> </div> <div> <input type="text" formControlName="ipInvalid" [pattern]="ipRegex" /> <span *ngIf="form.hasError('pattern', ['ipInvalid'])">Pattern error</span> </div> <div> <input type="text" formControlName="ipWrongValid" [pattern]="ipRegex" /> <span *ngIf="form.hasError('pattern', ['ipWrongValid'])">Pattern error</span> </div> </form>
TypeScript组件代码
export class App { ipRegex = '^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\/([1-2][0-9]|3[0-2]|[0-9]))?$'; form = new FormGroup({ ipValid: new FormControl('1.1.1.1'), ipInvalid: new FormControl('1...'), ipWrongValid: new FormControl('123.123'), }); }
正则测试对比
使用new RegExp()构造正则时出现误判:
const str = '123.123'; const regex = new RegExp('^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\/([1-2][0-9]|3[0-2]|[0-9]))?$'); console.log(regex.test(str)); // 返回true
使用正则字面量测试结果正确:
const str = '123.123'; /^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\/([1-2][0-9]|3[0-2]|[0-9]))?$/.test(str); // 返回false
问题原因
核心问题在于字符串中的转义字符处理逻辑:
- 正则字面量中,
\是正则的转义符,\.表示匹配字面意义的点号,\/表示匹配字面意义的斜杠。 - 但在JavaScript字符串中,
\本身是转义字符,若要在字符串中表示一个\,必须写成\\。
你当前的ipRegex字符串中所有\都未转义,导致:
\.(...)被JavaScript解析为.(...),正则中的.变成了匹配任意单个字符的通配符,而非字面意义的点号。- 这种情况下,
123.123这类字符串会被错误拆分匹配:将字符串中的数字字符当作分隔符(因为.可匹配任意字符),满足正则的四段结构,从而误判为有效IP。
解决方案
将ipRegex字符串中的所有\替换为\\,确保转义字符正确传递给正则表达式:
export class App { // 所有\转义为\\,保证正则解析正确 ipRegex = '^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\\/([1-2][0-9]|3[0-2]|[0-9]))?$'; form = new FormGroup({ ipValid: new FormControl('1.1.1.1'), ipInvalid: new FormControl('1...'), ipWrongValid: new FormControl('123.123'), }); }
修改后,正则中的\\.会被正确解析为\.(匹配字面点号),\\/解析为\/(匹配字面斜杠),此时123.123这类不符合IP格式的字符串会被正确判定为无效。
内容的提问来源于stack exchange,提问作者Gregor
相关产品推荐
相关产品推荐

