返回经验列表
正则表达式表单校验开发实战

正则表达式校验美国地址:邮编、州缩写与街道格式全解析

Petmind2026-07-2410分钟阅读

正则表达式校验美国地址

在开发表单系统时,前端即时校验能显著提升用户体验。正则表达式是成本最低、响应最快的校验方案。本文提供一套完整的美国地址字段正则校验规则,覆盖邮编、州缩写、街道地址等核心字段。

邮编 (ZIP Code) 校验

基础 5 位邮编

```javascript

const ZIP_CODE_REGEX = /^d{5}$/;

// 测试

console.log(ZIP_CODE_REGEX.test("90210")); // true

console.log(ZIP_CODE_REGEX.test("9021")); // false

console.log(ZIP_CODE_REGEX.test("902101")); // false

console.log(ZIP_CODE_REGEX.test("90a10")); // false

```

ZIP+4 扩展格式

```javascript

const ZIP_PLUS_4_REGEX = /^d{5}-d{4}$/;

// 允许两种格式

const ZIP_FLEXIBLE_REGEX = /^d{5}(-d{4})?$/;

console.log(ZIP_FLEXIBLE_REGEX.test("90210")); // true

console.log(ZIP_FLEXIBLE_REGEX.test("90210-1234")); // true

console.log(ZIP_FLEXIBLE_REGEX.test("90210-12")); // false

```

Python 实现

```python

import re

ZIP_PATTERNS = {

'strict_5': re.compile(r'^d{5}$'),

'zip_plus_4': re.compile(r'^d{5}-d{4}$'),

'flexible': re.compile(r'^d{5}(-d{4})?$')

}

def validate_zip(zip_code, allow_plus_4=True):

pattern = ZIP_PATTERNS['flexible'] if allow_plus_4 else ZIP_PATTERNS['strict_5']

return bool(pattern.match(zip_code))

批量测试

test_zips = ["90210", "90210-1234", "1234", "90210-12", "9021O"]

for z in test_zips:

print(f"{z}: {validate_zip(z)}")

```

州缩写 (State Code) 校验

美国有 50 个州 + DC + 5 个海外领地,共 56 个有效州代码。

完整州代码列表

```javascript

const VALID_STATES = new Set([

'AL','AK','AZ','AR','CA','CO','CT','DE','FL','GA',

'HI','ID','IL','IN','IA','KS','KY','LA','ME','MD',

'MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ',

'NM','NY','NC','ND','OH','OK','OR','PA','RI','SC',

'SD','TN','TX','UT','VT','VA','WA','WV','WI','WY',

'DC', // 华盛顿特区

'PR','VI','GU','AS','MP' // 海外领地

]);

function validateState(state) {

return VALID_STATES.has(state.toUpperCase());

}

```

带自动补全的州代码校验

```javascript

const STATE_NAMES = {

'CA': 'California', 'NY': 'New York', 'TX': 'Texas',

'FL': 'Florida', 'IL': 'Illinois', 'PA': 'Pennsylvania'

// ... 完整列表

};

function normalizeState(input) {

const upper = input.trim().toUpperCase();

// 直接匹配缩写

if (VALID_STATES.has(upper)) {

return { valid: true, code: upper, name: STATE_NAMES[upper] };

}

// 尝试匹配全称

const stateEntry = Object.entries(STATE_NAMES)

.find(([code, name]) => name.toLowerCase() === input.toLowerCase());

if (stateEntry) {

return { valid: true, code: stateEntry[0], name: stateEntry[1] };

}

return { valid: false, code: null, name: null };

}

```

街道地址 (Street Address) 校验

基础街道格式

```javascript

// 匹配 "123 Main St" 或 "4567 Oak Avenue"

const STREET_REGEX = /^d+s+[A-Za-z0-9s.-]+(?:s+(?:St|Street|Ave|Avenue|Rd|Road|Blvd|Boulevard|Dr|Drive|Ln|Lane|Ct|Court|Way|Pl|Place|Terrace|Circle|Highway|Hwy|Route|Rte))?$/i;

// 更严格的版本(要求包含街道类型)

const STREET_STRICT_REGEX = /^d+s+[A-Za-z0-9s.-]+s+(?:St|Street|Ave|Avenue|Rd|Road|Blvd|Boulevard|Dr|Drive|Ln|Lane|Ct|Court|Way|Pl|Place|Circle|Hwy|Highway)$/i;

```

公寓/套房号 (Address Line 2)

```javascript

// 匹配 Apt 5B, Suite 100, Unit 2A, #123

const APT_REGEX = /^(?:Apt|Apartment|Suite|Ste|Unit|#|Fl|Floor)s*[A-Za-z0-9-]+$/i;

// 更宽松的版本,允许 PO Box

const ADDRESS_LINE2_REGEX = /^(?:(?:Apt|Apartment|Suite|Ste|Unit|#|Fl|Floor)s*[A-Za-z0-9-]+|P.?O.?s*Boxs*d+)$/i;

```

完整街道校验函数

```python

import re

STREET_TYPES = {

'st': 'Street', 'street': 'Street',

'ave': 'Avenue', 'avenue': 'Avenue',

'blvd': 'Boulevard', 'boulevard': 'Boulevard',

'rd': 'Road', 'road': 'Road',

'dr': 'Drive', 'drive': 'Drive',

'ln': 'Lane', 'lane': 'Lane',

'ct': 'Court', 'court': 'Court',

'way': 'Way', 'pl': 'Place', 'place': 'Place',

'cir': 'Circle', 'circle': 'Circle',

'hwy': 'Highway', 'highway': 'Highway'

}

class AddressValidator:

def __init__(self):

self.zip_pattern = re.compile(r'^d{5}(-d{4})?$')

self.state_pattern = re.compile(r'^[A-Z]{2}$')

self.street_pattern = re.compile(

r'^d+s+[A-Za-z0-9s.-]+(?:s+(?:' +

'|'.join(STREET_TYPES.keys()) +

r'))?$',

re.IGNORECASE

)

def validate_zip(self, zip_code):

return bool(self.zip_pattern.match(zip_code))

def validate_state(self, state):

if not self.state_pattern.match(state):

return False

return state.upper() in self._get_all_state_codes()

def validate_street(self, street):

return bool(self.street_pattern.match(street))

def validate_full_address(self, address):

"""验证完整地址对象"""

errors = []

if not self.validate_street(address.get('street', '')):

errors.append("街道格式不正确")

if not address.get('city'):

errors.append("城市不能为空")

if not self.validate_state(address.get('state', '')):

errors.append("州缩写格式不正确")

if not self.validate_zip(address.get('zip', '')):

errors.append("邮编格式不正确")

return {

"valid": len(errors) == 0,

"errors": errors

}

def _get_all_state_codes(self):

return {

'AL','AK','AZ','AR','CA','CO','CT','DE','FL','GA',

'HI','ID','IL','IN','IA','KS','KY','LA','ME','MD',

'MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ',

'NM','NY','NC','ND','OH','OK','OR','PA','RI','SC',

'SD','TN','TX','UT','VT','VA','WA','WV','WI','WY','DC'

}

```

城市 (City) 校验

城市名称通常不需要严格的正则校验,但需要一些基本规则:

```javascript

const CITY_REGEX = /^[A-Za-zs.-']{2,50}$/;

function validateCity(city) {

if (!city || city.length < 2) return { valid: false, error: "城市名称太短" };

if (city.length > 50) return { valid: false, error: "城市名称太长" };

if (!CITY_REGEX.test(city)) return { valid: false, error: "城市名称包含非法字符" };

return { valid: true };

}

```

完整表单校验方案

React Hook 实现

```typescript

import { useState, useCallback } from 'react';

interface AddressForm {

street: string;

apartment: string;

city: string;

state: string;

zip: string;

}

interface ValidationResult {

valid: boolean;

errors: Record<string, string>;

}

export function useAddressValidation() {

const [errors, setErrors] = useState<Record<string, string>>({});

const validate = useCallback((form: AddressForm): ValidationResult => {

const newErrors: Record<string, string> = {};

// 街道校验

if (!form.street || form.street.length < 3) {

newErrors.street = "请输入有效的街道地址";

}

// 城市校验

if (!form.city || !/^[A-Za-zs.-']{2,50}$/.test(form.city)) {

newErrors.city = "请输入有效的城市名称";

}

// 州校验

const validStates = new Set(['AL','AK','AZ','AR','CA','CO','CT','DE','FL','GA','HI','ID','IL','IN','IA','KS','KY','LA','ME','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ','NM','NY','NC','ND','OH','OK','OR','PA','RI','SC','SD','TN','TX','UT','VT','VA','WA','WV','WI','WY','DC']);

if (!validStates.has(form.state.toUpperCase())) {

newErrors.state = "请输入有效的州缩写(如 CA, NY, TX)";

}

// 邮编校验

if (!/^d{5}(-d{4})?$/.test(form.zip)) {

newErrors.zip = "请输入有效的 ZIP Code(如 90210 或 90210-1234)";

}

setErrors(newErrors);

return { valid: Object.keys(newErrors).length === 0, errors: newErrors };

}, []);

return { validate, errors };

}

```

校验规则速查表

字段正则表达式示例说明
邮编`^\d{5}(-\d{4})?$`90210, 90210-12345位或5+4位
州缩写`^[A-Z]{2}$`CA, NY, TX两字母大写
街道`^\d+\s+[A-Za-z0-9\s\.\-]+`123 Main St门牌号+街道
公寓号`^(AptSuiteUnit#)\s*[A-Za-z0-9\-]+$`Apt 5B可选字段
城市`^[A-Za-z\s\.\-']{2,50}$`Los Angeles2-50字符

总结

正则表达式是美国地址前端校验最轻量、最高效的方案。通过本文提供的完整正则集合,你可以快速构建一个可靠的地址表单校验系统。对于生产环境,建议将正则校验作为第一层过滤,再结合 USPS API 进行第二层精确验证。

返回经验列表