Chapter 8: Practical Application Scenarios

Haiyue
9min
// Comprehensive Form Validator
class FormValidator {
    constructor() {
        this.validators = {
            email: this.validateEmail,
            phone: this.validatePhone,
            password: this.validatePassword,
            url: this.validateUrl,
            date: this.validateDate,
            creditCard: this.validateCreditCard,
            idCard: this.validateIdCard
        };
    }

    validateEmail(value) {
        const pattern = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
        return {
            valid: pattern.test(value) && value.length <= 254,
            message: pattern.test(value) ? '' : 'Please enter a valid email address'
        };
    }

    validatePhone(value, country = 'china') {
        const patterns = {
            china: /^1[3-9]\d{9}$/,
            usa: /^[2-9]\d{2}[2-9]\d{2}\d{4}$/,
            international: /^\+?[1-9]\d{1,14}$/
        };

        const cleanValue = value.replace(/\D/g, '');
        const pattern = patterns[country] || patterns.international;
        const valid = pattern.test(cleanValue);

        return {
            valid,
            message: valid ? '' : `Please enter a valid ${country === 'china' ? 'Chinese ' : ''}phone number`
        };
    }

    validatePassword(value, options = {}) {
        const {
            minLength = 8,
            requireUppercase = true,
            requireLowercase = true,
            requireNumbers = true,
            requireSpecialChars = true
        } = options;

        const errors = [];

        if (value.length < minLength) {
            errors.push(`Password must be at least ${minLength} characters`);
        }

        if (requireUppercase && !/[A-Z]/.test(value)) {
            errors.push('Must contain uppercase letter');
        }

        if (requireLowercase && !/[a-z]/.test(value)) {
            errors.push('Must contain lowercase letter');
        }

        if (requireNumbers && !/\d/.test(value)) {
            errors.push('Must contain number');
        }

        if (requireSpecialChars && !/[!@#$%^&*(),.?":{}|<>]/.test(value)) {
            errors.push('Must contain special character');
        }

        return {
            valid: errors.length === 0,
            message: errors.join(', ')
        };
    }

    validateUrl(value) {
        const pattern = /^https?:\/\/(?:[-\w.])+(?:\:[0-9]+)?(?:\/(?:[\w\/_.])*)?(?:\?(?:[\w&=%.])*)?(?:\#(?:[\w.])*)?$/;
        return {
            valid: pattern.test(value),
            message: pattern.test(value) ? '' : 'Please enter a valid URL'
        };
    }

    validateDate(value, format = 'YYYY-MM-DD') {
        const patterns = {
            'YYYY-MM-DD': /^\d{4}-\d{2}-\d{2}$/,
            'DD/MM/YYYY': /^\d{2}\/\d{2}\/\d{4}$/,
            'MM/DD/YYYY': /^\d{2}\/\d{2}\/\d{4}$/
        };

        const pattern = patterns[format];
        if (!pattern || !pattern.test(value)) {
            return {
                valid: false,
                message: `Please enter a valid date format (${format})`
            };
        }

        // Validate date validity
        let date;
        if (format === 'YYYY-MM-DD') {
            date = new Date(value);
        } else {
            const parts = value.split(/[\/\-]/);
            if (format === 'DD/MM/YYYY') {
                date = new Date(parts[2], parts[1] - 1, parts[0]);
            } else { // MM/DD/YYYY
                date = new Date(parts[2], parts[0] - 1, parts[1]);
            }
        }

        const valid = !isNaN(date.getTime());
        return {
            valid,
            message: valid ? '' : 'Please enter a valid date'
        };
    }

    validateCreditCard(value) {
        const cleanValue = value.replace(/\D/g, '');

        // Luhn algorithm validation
        const luhnCheck = (num) => {
            let sum = 0;
            let isEven = false;

            for (let i = num.length - 1; i >= 0; i--) {
                let digit = parseInt(num[i]);

                if (isEven) {
                    digit *= 2;
                    if (digit > 9) digit -= 9;
                }

                sum += digit;
                isEven = !isEven;
            }

            return sum % 10 === 0;
        };

        const cardTypes = {
            visa: /^4\d{12}(\d{3})?$/,
            mastercard: /^5[1-5]\d{14}$/,
            amex: /^3[47]\d{13}$/,
            discover: /^6011\d{12}$/
        };

        let cardType = 'unknown';
        for (const [type, pattern] of Object.entries(cardTypes)) {
            if (pattern.test(cleanValue)) {
                cardType = type;
                break;
            }
        }

        const valid = cardType !== 'unknown' && luhnCheck(cleanValue);

        return {
            valid,
            cardType,
            message: valid ? '' : 'Please enter a valid credit card number'
        };
    }

    validateIdCard(value) {
        // Chinese ID card validation
        const pattern = /^\d{17}[\dXx]$/;
        if (!pattern.test(value)) {
            return {
                valid: false,
                message: 'ID card number format is incorrect'
            };
        }

        // Check digit validation
        const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
        const codes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];

        let sum = 0;
        for (let i = 0; i < 17; i++) {
            sum += parseInt(value[i]) * weights[i];
        }

        const expectedCode = codes[sum % 11];
        const actualCode = value[17].toUpperCase();

        return {
            valid: expectedCode === actualCode,
            message: expectedCode === actualCode ? '' : 'ID card number validation failed'
        };
    }

    // Batch validation
    validateForm(formData, rules) {
        const results = {};
        let isValid = true;

        for (const [field, value] of Object.entries(formData)) {
            if (rules[field]) {
                const rule = rules[field];
                const validator = this.validators[rule.type];

                if (validator) {
                    const result = validator.call(this, value, rule.options);
                    results[field] = result;

                    if (!result.valid) {
                        isValid = false;
                    }
                }
            }
        }

        return {
            valid: isValid,
            fields: results
        };
    }
}

// Usage example
const validator = new FormValidator();

const formData = {
    email: 'user@example.com',
    phone: '13812345678',
    password: 'MyPassword123!',
    website: 'https://example.com',
    birthday: '1990-01-01',
    creditCard: '4111111111111111'
};

const validationRules = {
    email: { type: 'email' },
    phone: { type: 'phone', options: 'china' },
    password: {
        type: 'password',
        options: {
            minLength: 8,
            requireSpecialChars: true
        }
    },
    website: { type: 'url' },
    birthday: { type: 'date', options: 'YYYY-MM-DD' },
    creditCard: { type: 'creditCard' }
};

const result = validator.validateForm(formData, validationRules);
console.log('Form validation result:', result);

// Output validation information for each field
Object.entries(result.fields).forEach(([field, validation]) => {
    console.log(`${field}: ${validation.valid ? 'Valid' : validation.message}`);
});

Summary

This chapter demonstrates the application of regular expressions in various scenarios through practical cases:

  1. Email Validation: From simple to complex, considering internationalization support
  2. Phone Numbers: Supporting multiple country formats with formatting capabilities
  3. URL Processing: Validating, parsing, and extracting various links
  4. Password Strength: Multi-level validation and security policy implementation
  5. Date and Time: Multiple format support and intelligent parsing
  6. IP Addresses: IPv4/IPv6 validation and address classification
  7. Comprehensive Application: Complete form validator implementation

Through these practical cases, we can see the powerful capabilities and wide application of regular expressions in actual development. Mastering these common patterns can greatly improve development efficiency and data validation accuracy.

Practice Exercises

Exercise 1: Social Media Extractor

Write a function to extract all social media links (Twitter, Facebook, Instagram, etc.) from text.

Exercise 2: License Plate Validator

Write a Chinese license plate validator that supports both new energy and traditional license plate formats.

Exercise 3: Document Parser

Write a simple Markdown parser that extracts elements like headers, links, and images.

These exercises will help you further consolidate your skills in applying regular expressions in actual projects.