- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
Regular Expressions Without Fear: The Dozen Pieces You Actually Need
About Post
There's a well-known joke: you have a problem, you decide to use a regular expression, and now you have two problems.
It's funny because regex looks like a cat walked across the keyboard. ^(?:[a-z0-9]+-)*[a-z0-9]+$ isn't exactly friendly. But here's the secret most tutorials bury: the regex you'll write in everyday work uses about a dozen building blocks. Learn those, plus two or three traps, and regex goes from scary to one of the most useful small tools you own.
Let's build one up from nothing, then look at the traps and the times you shouldn't use regex at all. Examples are in PHP, but almost everything here works the same in JavaScript, Python and your editor's search box.
The dozen building blocks
| Pattern | Means | Example match |
|---|---|---|
abc | Literally "abc" | abc |
. | Any single character (except newline) | a, 7, - |
\d \w \s | A digit, a word character, whitespace | 7, a, space |
[aeiou] | One character from the set | e |
[^0-9] | One character not in the set | x |
* + ? | 0 or more, 1 or more, 0 or 1 of the previous thing | \d+ matches 2025 |
{4} {2,5} | Exactly 4, between 2 and 5 | \d{4} matches 2025 |
^ $ | Start and end of the string | (positions, not characters) |
\b | A word boundary | \bcat\b skips "category" |
(…) a|b | A group; either a or b | (jpg|png) |
\. | Escape a special character to match it literally | . |
That's it. Everything else is combining these.
Building one, step by step
Say invoice references look like INV-2025-0042: the letters INV, a dash, a four-digit year, a dash, and a four-digit number. We want to check a reference and pull out the year and number.
- The literal part:
INV- - Four digits for the year:
INV-\d{4} - Another dash and four more digits:
INV-\d{4}-\d{4} - Anchor it, so
XXINV-2025-0042-EXTRAdoesn't sneak through:^INV-\d{4}-\d{4}$ - Capture the parts we care about, with names so the code reads well:
$pattern = '/^INV-(?<year>\d{4})-(?<number>\d{4})$/';
if (preg_match($pattern, 'INV-2025-0042', $m)) {
echo $m['year']; // 2025
echo $m['number']; // 0042
}
Read it left to right and it's almost a sentence. That's the trick: build regex in small steps and test after each one, instead of writing the whole thing at once and praying.
Forgetting the anchors is the most common bug in validation regex. Without ^ and $, a pattern only asks "does this appear somewhere in the string?", which is rarely what validation means.
Groups: three flavours
- Capturing
(\d{4}): remembers what it matched, so you can use it ($m[1]). - Named
(?<year>\d{4}): same, but you get$m['year']. Use these whenever you have more than one group. Future you will be grateful. - Non-capturing
(?:jpg|png): groups things for|or a quantifier without remembering them. Keeps your match array clean.
The trap everyone falls into: greedy vs lazy
Quantifiers like * and + are greedy: they grab as much as they can while still allowing a match. Watch what happens:
$html = '<b>one</b> and <b>two</b>';
preg_match('/<b>(.*)<\/b>/', $html, $m);
// $m[1] is "one</b> and <b>two" (greedy: ran to the LAST </b>)
preg_match('/<b>(.*?)<\/b>/', $html, $m);
// $m[1] is "one" (lazy: stopped at the FIRST </b>)
Adding ? after a quantifier makes it lazy: match as little as possible. Often an even better fix is to be specific about what you allow: [^<]* ("anything except a <") can't overshoot at all.
Flags worth knowing
i: case-insensitive./^inv-/imatches "INV-" and "inv-".u: treat the pattern and string as UTF-8. In PHP, always add this when the input might contain non-English text, or.and character classes work on bytes and split characters in half. With it,\p{L}matches a letter in any language.m: makes^and$match at each line, not just the whole string.x: ignores whitespace in the pattern so you can space it out and add comments. Great for long patterns.
Patterns you'll actually use
| Job | Pattern |
|---|---|
| Collapse repeated whitespace | preg_replace('/\s+/u', ' ', $s) |
| Digits only | /^\d+$/ |
| A URL slug | /^[a-z0-9]+(?:-[a-z0-9]+)*$/ |
| Date shape YYYY-MM-DD | /^\d{4}-\d{2}-\d{2}$/ |
| Find TODOs in code | /\bTODO\b:?\s*(.*)$/m |
Notice the word shape on the date row. That regex happily accepts 2025-02-31. Regex checks what text looks like, not whether it makes sense. For real dates, use checkdate(), Carbon, or Laravel's date_format:Y-m-d rule.
The rule of thumb: regex is great for shape (does this look like a reference, a slug, a postcode?) and for finding or replacing text. It's the wrong tool for meaning (is this a real date, a deliverable email, valid HTML?).
When not to use regex
- Email validation. The full rules are famously hairy. Use
filter_var($email, FILTER_VALIDATE_EMAIL)or Laravel'semailrule, and confirm by actually sending an email. - Parsing HTML or XML. Nesting breaks regex quickly. Use a real parser:
DOMDocument, or the new HTML5-awareDom\HTMLDocumentadded in PHP 8.4. - URLs, JSON, CSV.
parse_url(),json_decode()andfgetcsv()handle edge cases you haven't thought of. - Untrusted input with a complex pattern. Nested quantifiers like
(a+)+$can take an enormous amount of time on certain inputs ("catastrophic backtracking"), which attackers can use as a denial of service. In PHP,preg_matchthen returnsfalseinstead of 0, so check for it and look atpreg_last_error_msg().
How to test without fear
Two habits make regex safe to work with:
- Use a visual tester. regex101.com explains every part of your pattern in plain English and highlights matches as you type. Pick the PCRE flavour for PHP, or ECMAScript for JavaScript, because the details differ.
- Pin it with a test. A few lines with good and bad examples, so the next person who "improves" the pattern finds out immediately if they broke it.
public static function references(): array
{
return [
['INV-2025-0042', true],
['inv-2025-0042', false],
['INV-2025-42', false],
['XINV-2025-0042', false],
];
}
The PHP manual's PCRE pattern syntax page is dense but complete when you need the details.
What's the regex you've copied from Stack Overflow so many times you should probably just learn it? For a lot of us, it's the one for trimming whitespace.

Be first to comment it...