آزمایشگر عبارات منظم
عبارات منظم را روی یک رشته آزمایش کنید و تمام تطابقها را برجستهشده ببینید
الگو
رشته آزمایشی
عبارت منظم چیست؟
عبارت منظم (regex یا regexp) دنبالهای از کاراکترها است که یک الگوی جستجو را تعریف میکند. آزمایشگرهای regex به شما امکان میدهند یک الگو بنویسید، آن را روی متن نمونه اجرا کنید و تمام تطابقها را بلادرنگ برجستهشده ببینید. این مفهوم به کارهای ریاضیدان Stephen Kleene درباره زبانهای منظم در دهه ۱۹۵۰ برمیگردد، و Ken Thompson اولین موتور regex را در ۱۹۶۸ درون ویرایشگر متن QED ساخت.
موتور regex یک الگو را از چپ به راست میخواند و کاراکترهای ورودی را هنگام تلاش برای تطابق مصرف میکند. وقتی یک تطابق جزئی شکست میخورد، از بازگشت به عقب (backtracking) استفاده میکند: موتور یک قدم به عقب برمیگردد و مسیرهای جایگزین در الگو را امتحان میکند. برخی موتورها (مانند RE2 که در Go استفاده میشود) با تبدیل الگوها به ماشین حالت متناهی قطعی (DFA) از بازگشت به عقب کاملاً اجتناب میکنند، که تطابق در زمان خطی را تضمین میکند اما از ویژگیهایی مانند ارجاعات پشتی پشتیبانی نمیکند.
نحو regex بهصورت آزاد استانداردسازی شده است. PCRE (عبارات منظم سازگار با Perl) رایجترین نوع است که توسط PHP، ماژول re پایتون و JavaScript با تفاوتهای جزئی پشتیبانی میشود. POSIX نحوی محدودتر تعریف میکند که توسط grep و sed استفاده میشود. این تفاوتها هنگام انتقال الگوها بین زبانها اهمیت دارند: یک lookahead که در JavaScript کار میکند ممکن است در موتور RE2 مربوط به Go اصلاً کامپایل نشود.
چرا از آزمایشگر Regex آنلاین استفاده کنیم؟
نوشتن regex در یک فایل کد به معنای ذخیره، اجرا و بررسی خروجی هر بار که الگو را تنظیم میکنید است. یک آزمایشگر regex مبتنی بر مرورگر این حلقه بازخورد را به صفر میرساند: تایپ میکنید، تطابقها را میبینید.
کاربردهای آزمایشگر Regex
مرجع سریع نحو Regex
جدول زیر پرکاربردترین نشانههای regex را پوشش میدهد. اینها در JavaScript، Python، Go، PHP و اکثر موتورهای سازگار با PCRE کار میکنند. پسوندهای خاص هر زبان (مانند الگوهای شرطی Python یا گروههای نامگذاریشده JavaScript با نحو \k) در بخش نمونههای کد ذکر شدهاند.
| الگو | نام | توضیح |
|---|---|---|
| . | Any character | Matches any single character except newline (unless s flag is set) |
| \d | Digit | Matches [0-9] |
| \w | Word character | Matches [a-zA-Z0-9_] |
| \s | Whitespace | Matches space, tab, newline, carriage return, form feed |
| \b | Word boundary | Matches the position between a word character and a non-word character |
| ^ | Start of string/line | Matches the start of the input; with m flag, matches start of each line |
| $ | End of string/line | Matches the end of the input; with m flag, matches end of each line |
| * | Zero or more | Matches the preceding token 0 or more times (greedy) |
| + | One or more | Matches the preceding token 1 or more times (greedy) |
| ? | Optional | Matches the preceding token 0 or 1 time |
| {n,m} | Quantifier range | Matches the preceding token between n and m times |
| () | Capturing group | Groups tokens and captures the matched text for back-references |
| (?:) | Non-capturing group | Groups tokens without capturing the matched text |
| (?=) | Positive lookahead | Matches a position followed by the given pattern, without consuming it |
| (?<=) | Positive lookbehind | Matches a position preceded by the given pattern, without consuming it |
| [abc] | Character class | Matches any one of the characters inside the brackets |
| [^abc] | Negated class | Matches any character not inside the brackets |
| | | Alternation | Matches the expression before or after the pipe |
توضیح پرچمهای Regex
پرچمها (که modifierها هم نامیده میشوند) نحوه پردازش الگو توسط موتور را تغییر میدهند. در JavaScript آنها را بعد از اسلش پایانی اضافه میکنید: /pattern/gi. در Python آنها را بهعنوان آرگومان دوم ارسال میکنید: re.findall(pattern, text, re.IGNORECASE | re.MULTILINE). همه پرچمها در هر زبانی در دسترس نیستند.
| پرچم | نام | رفتار |
|---|---|---|
| g | Global | Find all matches, not just the first one |
| i | Case-insensitive | Letters match both uppercase and lowercase |
| m | Multiline | ^ and $ match start/end of each line, not just the whole string |
| s | Dot-all | . matches newline characters as well |
| u | Unicode | Treat the pattern and subject as a Unicode string; enables \u{FFFF} syntax |
| y | Sticky | Matches only from the lastIndex position in the target string |
نمونههای کد
نمونههای عملی regex در JavaScript، Python، Go و خط فرمان. هر نمونه ساختار الگو، استخراج تطابق و خروجی را نشان میدهد.
// Match all email addresses in a string
const text = 'Contact us at support@example.com or sales@example.com'
const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g
const matches = text.matchAll(emailRegex)
for (const match of matches) {
console.log(match[0], 'at index', match.index)
}
// → "support@example.com" at index 14
// → "sales@example.com" at index 37
// Named capture groups (ES2018+)
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
const result = '2026-03-30'.match(dateRegex)
console.log(result.groups)
// → { year: "2026", month: "03", day: "30" }
// Replace with a callback
'hello world'.replace(/\b\w/g, c => c.toUpperCase())
// → "Hello World"import re
# Find all IPv4 addresses
text = 'Server 192.168.1.1 responded, fallback to 10.0.0.255'
pattern = r'\b(?:\d{1,3}\.){3}\d{1,3}\b'
matches = re.findall(pattern, text)
print(matches) # → ['192.168.1.1', '10.0.0.255']
# Named groups and match objects
date_pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'
m = re.search(date_pattern, 'Released on 2026-03-30')
if m:
print(m.group('year')) # → '2026'
print(m.group('month')) # → '03'
# Compile for repeated use (faster in loops)
compiled = re.compile(r'\b[A-Z][a-z]+\b')
words = compiled.findall('Hello World Foo bar')
print(words) # → ['Hello', 'World', 'Foo']package main
import (
"fmt"
"regexp"
)
func main() {
// Find all matches
re := regexp.MustCompile(`\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\b`)
text := "Contact support@example.com or sales@example.com"
matches := re.FindAllString(text, -1)
fmt.Println(matches)
// → [support@example.com sales@example.com]
// Named capture groups
dateRe := regexp.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`)
match := dateRe.FindStringSubmatch("2026-03-30")
for i, name := range dateRe.SubexpNames() {
if name != "" {
fmt.Printf("%s: %s\n", name, match[i])
}
}
// → year: 2026
// → month: 03
// → day: 30
// Replace with a function
result := re.ReplaceAllStringFunc(text, func(s string) string {
return "[REDACTED]"
})
fmt.Println(result)
// → Contact [REDACTED] or [REDACTED]
}# Find lines matching an IP address pattern
grep -E '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' access.log
# Extract email addresses from a file
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' contacts.txt
# Replace dates from YYYY-MM-DD to DD/MM/YYYY using sed
echo "2026-03-30" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/'
# → 30/03/2026
# Count matches per file in a directory
grep -rcE 'TODO|FIXME|HACK' src/
# → src/main.js:3
# → src/utils.js:1