Regex cheat sheet: meta karakterler, gruplar ve lookaround’lar (tam referans)
Düzenli ifade, metin eşleştirmek için kullanılan küçük bir desen dilidir. \d+ “bir veya daha fazla rakam” anlamına gelir, ^Error ise “Error ile başlayan bir satır” demektir. İşin tamamı budur. Bu cheat sheet, söz dizimini tek bir kaydırılabilir sayfada toplar: meta karakterler, niceleyiciler, çapalar, gruplar, lookaround’lar ve bayraklar, ek olarak bugün JavaScript veya Python’a yapıştırabileceğiniz 15’in üzerinde desen.
Yazı, karakter dizisinin ne olduğunu zaten bilen ve bir tur değil bir referans isteyen geliştiriciler için yazıldı. Yalnızca sembollere ihtiyacınız varsa Hızlı Referans Tablosu bölümüne atlayın. Bir regex’in sunucu kilitlediğini gördüyseniz, lookaround ve tuzaklar bölümlerini okuyun.
1. Regex nedir ve 2026’da neden hâlâ ihtiyacınız var
Bir regex, karakter dizisini tarayan ve ya eşleşen ya da başarısız olan bir durum makinesine derlenmiş bir desendir. Dilbilgisi küçüktür, kullanım alanları değildir.
Yapay zeka sizin için bir desen taslağı hazırlayabilir, ancak üç iş hâlâ regex’i elle yazan bir insana aittir:
- Log ayrıştırma: on milyon satırlık
nginxerişim logunuz var ve belirli bir kullanıcı ajanından gelen her 5xx isteğine ihtiyacınız var.grep -Eüzerinden 40 karakterlik bir regex saniyeler içinde çalışır; satır başına bir LLM çağrısı çalışmaz. - Form ve alan doğrulama: telefon numaraları, posta kodları, ISO zaman damgaları, lisans anahtarları. Desen girdinin yanında yaşar ve tarayıcıda her tuş vuruşunda çalışır.
- Toplu bul-ve-değiştir: bir adı yakalayıp yeniden eklemeniz gereken bin dosyayı yeniden düzenlemek.
sed,ripgrepve editörünüzdeki “Dosyalarda Değiştir” araçları regex’i yerel olarak konuşur.
Aynı araç kutusunun JSON tarafı için jq komut satırı cheat sheet yazımıza bakın.
1.1 Bir regex desenini nasıl okursunuz (5 saniyelik düzenli ifade öğreticisi)
Çoğu deseni soldan sağa, her seferinde bir token okumak daha kolaydır. Örnek olarak ^[A-Z]\w+\d{2,4}$ desenini ele alın:
^eşleşmeyi karakter dizisinin başına çapalar.[A-Z]tam olarak bir büyük harfle eşleşir.\w+bir veya daha fazla kelime karakteriyle eşleşir.\d{2,4}iki ile dört arasında rakamla eşleşir.$karakter dizisinin sonuna çapalar.
Beceri, önce çapaları, ardından karakter sınıflarını, sonra niceleyicileri okumaktır.
2. Hızlı referans tablosu
Çoğu okuyucunun geldiği bölüm burası. İhtiyacınız olanı kopyalayın.
Meta karakterler
| Desen | Eşleşir |
|---|---|
. | Yeni satır dışında herhangi bir karakter (veya s/dotall bayrağı ile herhangi bir karakter) |
\d | Bir rakam ([0-9], veya u bayrağı ile tüm Unicode rakamları) |
\D | Rakam olmayan bir karakter |
\w | Bir kelime karakteri ([A-Za-z0-9_]) |
\W | Kelime karakteri olmayan |
\s | Herhangi bir boşluk (boşluk, sekme, yeni satır, …) |
\S | Boşluk olmayan herhangi bir karakter |
Niceleyiciler
| Desen | Eşleşir |
|---|---|
* | 0 veya daha fazla (greedy) |
+ | 1 veya daha fazla (greedy) |
? | 0 veya 1 (greedy) |
{n} | Tam olarak n kez |
{n,m} | n ile m kez arasında |
{n,} | n veya daha fazla kez |
*?, +?, ??, {n,m}? | Her niceleyicinin lazy sürümü |
Çapalar
| Desen | Eşleşir |
|---|---|
^ | Karakter dizisinin başı (veya m bayrağı ile satırın başı) |
$ | Karakter dizisinin sonu (veya m bayrağı ile satırın sonu) |
\b | Kelime sınırı |
\B | Kelime olmayan sınır |
\A | Karakter dizisinin mutlak başı (Python) |
\Z | Karakter dizisinin mutlak sonu (Python) |
Karakter sınıfları
| Desen | Eşleşir |
|---|---|
[abc] | a, b, c karakterlerinden herhangi biri |
[^abc] | a, b, c dışındaki herhangi bir karakter |
[a-z] | Herhangi bir küçük harf |
[0-9] | Herhangi bir rakam |
\p{L} | Herhangi bir Unicode harfi (JS’de u bayrağı, Python re’de varsayılan) |
Gruplar
| Desen | Eşleşir |
|---|---|
(...) | Yakalama grubu |
(?:...) | Yakalama yapmayan grup |
(?<name>...) | İsimli yakalama (JS ES2018+); Python (?P<name>...) kullanır |
\1, \2 | Grup 1, 2’ye geriye başvuru |
Lookaround
| Desen | Eşleşir |
|---|---|
(?=...) | Pozitif lookahead |
(?!...) | Negatif lookahead |
(?<=...) | Pozitif lookbehind |
(?<!...) | Negatif lookbehind |
Bayraklar
| Bayrak | Etki |
|---|---|
i | Büyük-küçük harf duyarsız |
m | Çok satırlı: ^ ve $ her satırda eşleşir |
s | Dotall: . yeni satırlarla eşleşir |
g | Global (JS), tüm eşleşmeleri bulur |
u | Unicode modu |
y | Sticky (JS), lastIndex’e tutturulur |
3. Meta karakterler ve karakter sınıfları
3.1 Literaller ve özel karakterler
Çoğu karakter literaldir. Kendileri olarak istediğinizde kaçırılması gereken 12 meta karakter şunlardır:
. ^ $ * + ? ( ) [ ] { } | \
. kaçırmasını unutmak en yaygın regex hatasıdır. \. literal nokta ile eşleşir. Karakter sınıfının içinde [.] de literal nokta ile eşleşir, çünkü çoğu meta karakter [...] içinde gücünü kaybeder. İstisnalar: ], \, ^ (ilk olduğunda) ve - (ortada).
3.2 Karakter kısayolları
Kısayol sınıfları, Unicode ortaya çıkana kadar basit görünür:
// JavaScript — u bayrağı olmadan, \d yalnızca ASCII'dir
/\d/.test('5'); // true
/\d/.test('٥'); // false (Arapça-Hint rakamı)
/\d/u.test('٥'); // false — u ile bile, JS'de \d ASCII kalır
/\p{N}/u.test('٥'); // true — \p{N}, Unicode-aware rakam sınıfıdır
# Python — re modülü \d'yi varsayılan olarak Unicode olarak ele alır
import re
re.match(r'\d', '٥') # <Match span=(0, 1)>
re.match(r'(?a)\d', '٥') # None — (?a) ASCII'yi zorlar
Yalnızca İngilizce ASCII girdisiyle uğraşıyorsanız, \d ve [0-9] birbirinin yerine geçer. Bir kullanıcı aksanlı bir ad yapıştırdığı anda \w yerine \p{L} istersiniz.
3.3 Özel karakter sınıfları
// JavaScript
/[A-Za-z][A-Za-z0-9_-]{2,29}/.test('valid_handle-1'); // true
// Negasyon ve aralıkların birleşimi
/[^aeiou\s]/g // ünlü olmayan, boşluk olmayan herhangi bir karakter
Unicode kategorileri için \p{L} “herhangi bir harf”tir, \p{N} “herhangi bir sayı”dır, \p{Script=Han} “herhangi bir Han karakteri”dir. JavaScript u bayrağını gerektirir; Python \p{...}’i yalnızca PyPI’deki regex paketi aracılığıyla destekler, stdlib re ile değil.
Komut satırında çalışıyorsanız, POSIX karakter sınıflarıyla da karşılaşabilirsiniz:
| POSIX sınıfı | Eşleşir | ASCII karşılığı |
|---|---|---|
[[:alpha:]] | harfler | [A-Za-z] |
[[:digit:]] | rakamlar | [0-9] (\d) |
[[:alnum:]] | harfler + rakamlar | [A-Za-z0-9] |
[[:space:]] | boşluk | \s |
[[:upper:]] | büyük harf | [A-Z] |
[[:lower:]] | küçük harf | [a-z] |
POSIX sınıfları grep -E ve sed -E içinde çalışır. JavaScript veya Python re içinde çalışmazlar — bunların yerine \d, \s, \w kullanın.
4. Niceleyiciler ve greedy ile lazy
4.1 Temel niceleyiciler
/a*/.exec('aaab') // ['aaa'] — 0 veya daha fazla
/a+/.exec('aaab') // ['aaa'] — 1 veya daha fazla
/a?/.exec('aaab') // ['a'] — 0 veya 1
/a{2,3}/.exec('aaaab') // ['aaa'] — 2 ile 3
4.2 Greedy ve lazy
Varsayılan olarak niceleyiciler greedy’dir: alabildikleri kadar çok şey kaparlar, sonra tüm desenin uyması için geri çekilirler. Onları lazy’ye çevirmek için ? ekleyin.
const html = '<p>one</p><p>two</p>';
html.match(/<p>.*<\/p>/)[0]; // '<p>one</p><p>two</p>' (greedy ikisini de yer)
html.match(/<p>.*?<\/p>/)[0]; // '<p>one</p>' (lazy ilkinde durur)
Etiketler veya tırnak içindeki karakter dizileri çıkarırken neredeyse her zaman lazy sürümünü istersiniz. Daha iyi yol: .’dan tamamen kaçının ve negasyonlu bir sınıf kullanın. <p>[^<]*</p> deseni, <p>.*?</p>’den daha hızlıdır çünkü geri izlenecek hiçbir şey kalmaz.
4.3 Felaket geri izleme
Bir regex’in sunucu kilitleme yolu budur. Belirsiz bir örtüşme ile bir niceleyiciyi başka bir niceleyicinin içine yerleştirin, motor pes etmeden önce üstel sayıda yolu keşfeder.
// Bunu yapmayın
/(a+)+b/.test('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!'); // saniyeler sürer
41 a ardından ! için, motor b’nin eksik olduğuna karar vermeden önce kabaca 2^41 bölünme noktasını dener. Üç düzeltme:
- Deseni düzleştirin:
/a+b/aynı işi iç içe geçme olmadan yapar. - Atomik bir grup kullanın (Python
regex, PCRE, Java, Ruby):(?>a+)+bdesenindea+bir kez eşleştiğinde motor içine geri izlemeyi reddeder. - Motorları değiştirin: Go’nun
regexp’i, RE2 ve Rust’ınregexcrate’i doğrusal zamanlı bir NFA kullanır ve tasarım gereği felaket boyutunda geri izleyemezler.
JavaScript ve Python re her ikisi de geri izler ve stdlib’de atomik gruplara sahip değildir (Python’un PyPI regex paketi bunları ekler). Girdi uzunluğunu kontrol ettiğinizde sorun değildir. Girdi bir kullanıcıdan geldiğinde, önce uzunluğu doğrulayın veya RE2’ye karşı önceden derleyin.
5. Çapalar ve kelime sınırları
5.1 ^ ve $
Varsayılan olarak ^, tüm girdinin başıdır ve $, sonudur. m (çok satırlı) bayrağıyla, her satırın başı ve sonu olurlar:
const log = 'INFO start\nERROR boom\nINFO done';
log.match(/^ERROR.*/); // null — tek satır modu, ^ yalnızca dizin 0'da eşleşir
log.match(/^ERROR.*/m); // ['ERROR boom']
5.2 \b ve \B
\b, sıfır genişlikli bir iddiadır: bir kelime karakteri (\w) ile bir kelime olmayan karakter arasındaki konumla eşleşir. Tam kelime araması için yararlıdır:
/\bcat\b/.test('the cat sat'); // true
/\bcat\b/.test('concatenate'); // false
Kelime sınırları, varsayılan olarak ASCII olan \w üzerinde tanımlanır. Çince, Japonca ve Korece metinde kelimeler arasında boşluk yoktur, bu yüzden \b orada kelime kenarlarını algılamaz. Regex’ten önce bir tokenleştiriciye (jieba, MeCab) ihtiyacınız vardır.
5.3 Çok satırlı mod
import re
text = "INFO ok\nERROR fail\nINFO done\n"
re.findall(r'^ERROR.*$', text) # []
re.findall(r'^ERROR.*$', text, re.MULTILINE) # ['ERROR fail']
JavaScript’te aynı şey text.match(/^ERROR.*$/gm) olarak okunur. Her eşleşen satırı yakalamak için m’yi g ile birleştirin.
6. Gruplar, yakalama ve geriye başvurular
6.1 Yakalama grupları
Parantezler iki iş yapar: niceleyiciler için alt desenleri gruplandırırlar ve eşleşmeyi sonradan kullanmak üzere yakalarlar.
'2026-05-13'.match(/(\d{4})-(\d{2})-(\d{2})/);
// ['2026-05-13', '2026', '05', '13', index: 0, ...]
Gruplar, açılış parantezlerine göre soldan sağa numaralandırılır, 1’den başlar.
6.2 Yakalama yapmayan gruplar
Yalnızca gruplandırmaya ihtiyacınız olduğunda yakalamaya değil (?:...) kullanın. Daha hızlıdır ve numaralı grupları düzenli tutar:
/(?:https?):\/\/(\S+)/.exec('see https://go-tools.org');
// ['https://go-tools.org', 'go-tools.org']
// — protokol gruplandırılmış ama yakalanmamış; grup 1 sunucudur
6.3 İsimli gruplar
Grupları adlandırmak desenleri okunabilir ve refactor-güvenli hâle getirir.
// JavaScript (ES2018+)
const m = '2026-05-13'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
m.groups.year; // '2026'
# Python — (?P<...>) söz dizimine dikkat
import re
m = re.match(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})', '2026-05-13')
m.group('year') # '2026'
6.4 Geriye başvurular
Geriye başvurular, desenin sonraki bir bölümünün daha önceki bir yakalamanın eşleştirdiğini tekrarlamasına izin verir.
// Ardışık olarak tekrarlanan herhangi bir karakteri bul
'bookkeeper'.match(/(\w)\1/g); // ['oo', 'kk', 'ee']
// Eşleştirilmiş HTML etiketlerini ada göre eşleştir
const tag = /<(\w+)>(.*?)<\/\1>/;
'<b>bold</b>'.match(tag);
// ['<b>bold</b>', 'b', 'bold']
Python’da \1 hem desende hem de değiştirmede çalışır. İsimli başvurular desende (?P=name) olarak, re.sub değiştirmelerinde ise \g<name> olarak okunur.
7. Lookaround’lar: lookahead ve lookbehind
Lookaround’lar sıfır genişlikli iddialardır. Karakterleri tüketmeden bir koşulu kontrol ederler, böylece onları zincirleyebilirsiniz.
7.1 Lookahead
// Şifre: en az 8 karakter, bir rakam, bir büyük harf, bir küçük harf
const strong = /^(?=.*\d)(?=.*[A-Z])(?=.*[a-z]).{8,}$/;
strong.test('Hunter2!'); // true
strong.test('hunter2!'); // false — büyük harf yok
// Negatif lookahead — .tmp olmayan dosya adları
/^[\w-]+(?!\.tmp$)\.[a-z]+$/.test('report.csv'); // true
7.2 Lookbehind
Lookbehind, ayna görüntüsüdür: mevcut konumdan önce gelenin ne olduğunu iddia eder.
// Para birimi simgesinden sonraki fiyatı çıkar, sayıyı tut, $'ı at
'price: $42.50'.match(/(?<=\$)\d+(\.\d+)?/); // ['42.50', '.50']
// Negatif lookbehind — Bond'u eşleştir ama James Bond'u değil
'Mr. Bond'.match(/(?<!James )Bond/); // ['Bond']
'James Bond'.match(/(?<!James )Bond/); // null
7.3 JavaScript ile Python lookbehind karşılaştırması
İki motorun, bir deseni taşıdığınızda kırılacak kadar ayrıştığı az sayıdaki yerden biri burasıdır.
| Motor | Lookbehind uzunluğu |
|---|---|
| JavaScript (V8, SpiderMonkey, JSC 16.4+) | ES2018’den beri değişken genişlikli. (?<=\d+) geçerlidir. |
Python stdlib re | Yalnızca sabit genişlikli. (?<=\d+) error: look-behind requires fixed-width pattern hatası verir. |
Python regex PyPI paketi | Değişken genişlik desteklenir. import regex; regex.search(r'(?<=\d+)abc', '12abc'). |
Python’da geçici çözüm: lookbehind’ı bilinen bir tekrarla ((?<=\d{3})) yeniden yazın veya öneki yakalayın ve eşleştikten sonra dilimleyin.
8. Bayraklar ve değiştiriciler
8.1 i, büyük-küçük harf duyarsız
/error/i.test('FATAL ERROR'); // true
re.search(r'error', 'FATAL ERROR', re.IGNORECASE) # <Match span=(6, 11)>
8.2 m ve s
m, ^ ve $’ı satır başına çapalara çevirir. s (dotall), .’nın yeni satırlarla eşleşmesine izin verir. Bağımsızdırlar; her ikisini de istediğinizde birleştirin.
/<script>(.*?)<\/script>/s.exec('<script>\nalert(1)\n</script>')[1];
// '\nalert(1)\n' — s olmadan, . yeni satırları reddeder
8.3 g, global
JavaScript’te g, eşleşmenin kendisinden çok API’yi değiştirir. g olmadan String.match yakalama gruplarını döndürür; g ile her eşleşme karakter dizisini döndürür. Tüm eşleşmelerde yakalama gruplarını korumak için matchAll kullanın.
const text = 'a=1 b=2 c=3';
text.match(/(\w)=(\d)/); // gruplarla ilk eşleşme
text.match(/(\w)=(\d)/g); // ['a=1', 'b=2', 'c=3'] — grup yok
[...text.matchAll(/(\w)=(\d)/g)]; // her eşleşme, gruplarla birlikte
Python g kullanmaz. re.findall, re.finditer ve re.sub global varyantlardır.
8.4 u, Unicode ve \p{...}
// Herhangi bir Han karakterini eşleştir (Çince, Japonca kanji)
/\p{Script=Han}+/gu.test('Hello 世界'); // true
// Emoji eşleştir (genişletilmiş piktografik)
/\p{Extended_Pictographic}/u.test('👋'); // true
Python’da Unicode varsayılan olarak açıktır; Han aralığı için eşdeğeri re.findall(r'[一-鿿]+', text)’tir. Tam Unicode özellik kaçışları için PyPI regex paketini kullanın: regex.findall(r'\p{Script=Han}+', text).
9. Günlük olarak kullanacağınız yaygın desenler
9.1 E-posta doğrulama
Hangi sürüme ihtiyacınız olduğu konusunda dürüst olun.
// %95 deseni — çoğu form doğrulayıcısının kullandığı
const email = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
email.test('a@b.co'); // true
// "Gerçekten RFC 5322-ish olmak istiyorum" deseni
const rfc = /^[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])?)*$/;
Gerçek şu: yalın regex’te tam RFC 5322 e-posta doğrulaması yaklaşık 6000 karakter uzunluğundadır ve uç durumlarda hâlâ yanlış çalışır. %95 desenini kullanın, ardından bir doğrulama e-postası gönderin. Gerçekten işe yarayan tek test budur.
9.2 URL çıkarma
const urlPattern = /https?:\/\/[^\s<>"]+/g;
const found = 'See https://example.com/a?b=1 and http://x.io'.match(urlPattern);
// ['https://example.com/a?b=1', 'http://x.io']
Bir URL’yi çıkardıktan sonra genellikle sorgu karakter dizisini incelemek istersiniz. URL Kodlayıcı ve Çözücü aracımıza yapıştırın, yüzde-kodlanmış parametreleri bir bakışta okuyabilirsiniz. Ne zaman kodlayacağınız ve ne zaman çözeceğinizin tam tablosu için URL Kodlama ve Çözme Rehberi’ni okuyun.
9.3 Telefon numaraları
// E.164 — uluslararası, isteğe bağlı + ve 1-3 haneli ülke kodu
const e164 = /^\+?[1-9]\d{1,14}$/;
e164.test('+14155551234'); // true
// Ayırıcılarla Kuzey Amerika Numara Planı
const nanp = /^(\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$/;
nanp.test('(415) 555-1234'); // true
“Bu şekil makul mü” sorusunun ötesinde herhangi bir şey için libphonenumber kullanın. Regex bir alan kodunun var olup olmadığını doğrulayamaz.
9.4 IPv4 ve IPv6
// IPv4 — her oktet için katı 0-255
const ipv4 = /^((25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(25[0-5]|2[0-4]\d|1?\d?\d)$/;
ipv4.test('192.168.1.1'); // true
ipv4.test('999.0.0.1'); // false
// IPv6 — basitleştirilmiş form. Tam RFC 4291 deseni ~600 karakterdir.
const ipv6simple = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
ipv6simple.test('2001:0db8:85a3:0000:0000:8a2e:0370:7334'); // true
:: kısaltması, gömülü IPv4 ve bölge tanımlayıcıları olan gerçek IPv6 için node:net’in isIP()’sini veya Python’un ipaddress.ip_address()’ini kullanın. Bunu yalın regex’te yapmaya çalışmak önce bir geçiş ayini, ardından bir bakım yükü olur.
9.5 ISO 8601 tarihleri ve zaman damgaları
// Yalnızca tarih — YYYY-MM-DD
const isoDate = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
isoDate.test('2026-05-13'); // true
// Tarih + saat + isteğe bağlı kesirli saniyeler + Z veya ofset
const iso = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;
iso.test('2026-05-13T09:30:00.123Z'); // true
ISO 8601 basit görünür ve tuzaklarla doludur: artık saniyeler, hafta tarihleri (2026-W19), sıralı tarihler (2026-133). Epoch saniyeleri ile milisaniyeler ve zaman dilimi kaymaları için Unix Timestamp Rehberi’ne bakın.
10. Regex ile bul/değiştir iş akışları
10.1 JavaScript, $1 ile String.replace
// ABD tarihlerini yeniden biçimlendir: MM/DD/YYYY -> YYYY-MM-DD
'05/13/2026'.replace(/(\d{2})\/(\d{2})\/(\d{4})/, '$3-$1-$2');
// '2026-05-13'
// Değiştirme koşullu olduğunda bir geri çağırma kullanın
'price 42 dollars'.replace(/(\d+) dollars/, (_, n) => `$${n}`);
// 'price $42'
$1, $2, … numaralı gruplara başvurur. $<name> isimli gruplara başvurur. $& tam eşleşmedir; $$ literal $’dır.
10.2 Python, \1 ve geri çağırmalarla re.sub
import re
# Yukarıdakiyle aynı tarih yeniden biçimlendirmesi
re.sub(r'(\d{2})/(\d{2})/(\d{4})', r'\3-\1-\2', '05/13/2026')
# '2026-05-13'
# Geri çağırma — bir karakter dizisindeki her e-posta adresini büyük harf yap
def upper_email(m):
return m.group(0).upper()
re.sub(r'[\w.-]+@[\w.-]+', upper_email, 'mail me at hi@go-tools.org')
# 'mail me at HI@GO-TOOLS.ORG'
Değiştirmelerde Python \1 veya \g<name> kullanır. Ham karakter dizisi r'...' öneki önemlidir; onsuz \1 literal bir karakter olur.
10.3 CLI: sed, grep, ripgrep, jq
Komut satırında toplu yeniden düzenlemeler için regex betikten kabuğa taşınır:
# ripgrep — adı eklenmiş her TODO'yu bul
rg -n '\bTODO\(([^)]+)\)' --replace 'TODO(\1)'
# çapalarla grep -E — auth.log'dan başarısız giriş satırları
grep -E '^[A-Z][a-z]{2} +[0-9]+ .*Failed password' /var/log/auth.log
# sed — sondaki boşlukları, yerinde, bir ağaç boyunca temizle
find . -name '*.md' -print0 | xargs -0 sed -i -E 's/[[:space:]]+$//'
ripgrep, Rust’ın regex crate’ini kullanır (RE2-stili, doğrusal zaman, lookbehind yok). grep -E ve sed -E POSIX genişletilmiş regex kullanır ve bu da \d’den yoksundur; bunun yerine [0-9] ve [[:digit:]] kullanın. Veriler JSON olduğunda regex yerine jq’yu kullanın. Paralel bir referans kartı için jq cheat sheet’e bakın.
11. Yaygın tuzaklar
11.1 .’yı kaçırmayı unutmak
Yayınladığımız gerçek bir hata: bir log redaktörünün IP adreslerini maskelemesi gerekiyordu.
// Yanlış — '192a168b1c1' ile de eşleşir
/(\d+).(\d+).(\d+).(\d+)/.test('192a168b1c1'); // true
// Doğru
/(\d+)\.(\d+)\.(\d+)\.(\d+)/.test('192a168b1c1'); // false
Karakter sınıfının içinde . zaten literaldir, bu yüzden [.] ve \. her ikisi de çalışır. Başka yerlerde kaçırın.
11.2 Greedy .* çok fazla yer
'<a href="x"><b>bold</b></a>'.match(/<(.*)>/)[1];
// 'a href="x"><b>bold</b></a' — her şey!
Greedy .* karakter dizisinin sonuna kadar tarar, ardından > eşleşene kadar geri çekilir, yani girdideki son >. Ya lazy olun (.*?) ya da daha hızlı ve daha net biçimde negasyonlu bir sınıf kullanın ([^>]*).
11.3 Çok satırlı çapalar
Yaygın bir karışıklık: ^ ve $ varsayılan olarak yeni satır karakterleriyle eşleşmez. Tüm girdinin başında ve sonunda konumlarla eşleşirler. m bayrağını eklemek onları satır başına çapalara dönüştürür. s bayrağını eklemek .’nın yeni satırları geçmesine izin verir. Bunlar diktir ve log ayrıştırma için genellikle her ikisini de istersiniz.
11.4 ReDoS ve nasıl etkisiz hale getirilir
ReDoS (regex hizmet reddi), felaket geri izlemenin production-grade sürümüdür. Düzeltmeler:
- Statik analiz:
safe-regex,recheckve ESLint’inno-misleading-character-class’ı gibi araçlar, tehlikeli desenleri yayınlanmadan önce yakalar. - Atomik gruplar (Python
regex, PCRE, Ruby, Java):(?>...)motorun geri izleme sırasında gruba yeniden girmesini önler. - Possessive niceleyiciler (PCRE/Java’da
*+,++,?+): aynı fikir, daha kısa söz dizimi. - Geri izlemeyen bir motora geçin: Go’nun
regexp’i, RE2, Rust’ınregexcrate’i ve Pythonre2bağı doğrusal zamanda çalışır. ripgrep, vahşi doğadaki en popüler RE2 dağıtımıdır. - Önce girdi uzunluğunu doğrulayın. 10 KB’lık bir regex bombası bir hatadır; girdide 10 baytlık bir sınır bir satır koddur.
Regex ile eşleşen günlük sürücü araçların daha geniş bir envanteri için (biçimlendiriciler, çözücüler, dönüştürücüler) geliştirici araçları rehberimize bakın.
Karmaşık bir deseni yayına almadan önce, etkileşimli olarak test edin. regex101.com, PCRE, JavaScript, Python ve Go varyantları arasında geçiş yapar, her token’ı açıklar ve felaket boyutundaki desenleri tespit edebilmeniz için geri izlemeyi gösterir.
12. SSS
Regex * ile + arasındaki fark nedir?
* sıfır veya daha fazla olayla eşleşir (boş bir karakter dizisiyle eşleşebilir); + bir veya daha fazlasıyla eşleşir (en az birine ihtiyacı vardır). a* '', 'a', 'aaaa' ile eşleşir. a+ 'a' ve 'aaaa' ile eşleşir ancak '' ile değil.
Regex ile birden çok satırda nasıl eşleştirebilirim?
Çok satırlı bayrağı açın (JavaScript’te /.../m, Python’da re.MULTILINE), böylece ^ ve $ her satıra tutturulur. .’nın da yeni satırları geçmesine izin vermek için dotall bayrağını ekleyin (JavaScript’te s, Python’da re.DOTALL).
Regex JavaScript ve Python’da aynı mı?
Çekirdek söz dizimi (niceleyiciler, çapalar, karakter sınıfları, temel gruplar) %90 aynıdır. İki gerçek fark: JavaScript (ES2018+) değişken uzunluklu lookbehind’ı destekler ve isimli grupları (?<name>...) olarak yazar; Python stdlib re sabit genişlikli lookbehind gerektirir ve (?P<name>...) kullanır. Python’da değişken uzunluklu lookbehind için PyPI’den regex paketini yükleyin.
Regex’imde neden felaket geri izleme oluyor?
(a+)+ veya (a|a)* gibi örtüşen eşleşmeleri olan iç içe niceleyicileriniz vardır. Neredeyse eşleşen ancak sona yakın başarısız olan girdide motor iç niceleyicinin her bölünmesini dener (üstel sayıda yol). Bunu atomik bir grup (?>a+)+, possessive bir niceleyici a++ veya RE2 ya da Go’nun regexp’i gibi geri izlemeyen bir motora geçerek düzeltin.
JavaScript’te lookbehind kullanabilir miyim?
Evet. Pozitif (?<=...) ve negatif (?<!...) lookbehind, ES2018’den beri V8 (Chrome, Node.js), SpiderMonkey (Firefox) ve JavaScriptCore’da (Safari 16.4+) bulunmaktadır. Değişken uzunluklu lookbehind desteklenir. Daha eski Safari için Babel ile transpile edin veya new RegExp etrafında bir try/catch ile özellik algılaması yapın.
Regex’te literal bir nokta . ile nasıl eşleştirebilirim?
Ters eğik çizgi ile kaçırın: \. literal bir noktayla eşleşir. Karakter sınıfının içinde nokta zaten literaldir; hem [.] hem de [\.] çalışır. Sınıfın dışında, kaçırılmamış bir . “yeni satır dışında herhangi bir karakter” anlamına gelen bir meta karakterdir (veya dotall bayrağıyla herhangi bir karakter).
Regex’te \s ne anlama gelir?
\s herhangi bir boşluk karakteriyle eşleşir — boşluk, sekme, yeni satır, satır başı. Unicode modunda NBSP ile de eşleşir. \S bunun tersidir.
Düzenli ifadeler büyük-küçük harf duyarlı mıdır?
Varsayılan olarak, evet. JavaScript’te i bayrağını (/cat/i) veya Python’da re.IGNORECASE / (?i) kullanın.