Bir kez derleyin, sonra eşleştirin
Desenleri ters tırnaklı ham string literal'leri olarak yazın. Normal çift tırnaklı bir string'de her ters eğik çizgi ikiye katlanmalıdır ("\\d+") ve bu hızla okunamaz hale gelir.
regexp.MustCompile, desen geçersizse panic yapar; kaynak kodunuzdaki bir desen için istediğiniz de budur: bir yazım hatası ilk istekte değil, hemen başlangıçta başarısız olur. Kullanıcılardan ya da yapılandırmadan gelen desenler için regexp.Compile kullanın ve hatayı ele alın:
re, err := regexp.Compile(userPattern)
if err != nil {
return fmt.Errorf("bad pattern: %w", err)
}
Bir kez derleyin. Derlemek eşleştirmekten çok daha pahalıdır. İstek ya da satır başına çalışan bir fonksiyonun içindeki regexp.MustCompile bu işi her seferinde tekrarlar. Derlenmiş *regexp.Regexp'i paket seviyesindeki bir var'a ya da bir struct alanına koyun. Derlenmiş bir regexp'i aynı anda birçok goroutine'den kullanmak güvenlidir.
regexp.MatchString(pattern, s) tek bir çağrıda derler ve eşleştirir. Tek seferlik bir kontrol için uygundur, bir döngüde israftır.
Eşleşmeleri bulmak
Metot adları bir kalıbı izler: Find + All? + String? + Submatch? + Index?.
| Parça | Anlamı |
|---|---|
All | çakışmayan her eşleşme; bir n limiti alır (hepsi için -1) |
String | bir string üzerinde çalışır; o olmadan metot []byte alır ve döndürür |
Submatch | yakalama gruplarını da döndürür |
Index | metin yerine bayt konumları döndürür |
FindString eşleşme olmadığında "" döndürür; bu, boş bir string'le eşleşmekten ayırt edilemez. Desen boş metinle eşleşebiliyorsa FindStringIndex (eşleşme yoksa nil döndürür) kullanın ya da önce MatchString çağırın. All çeşitleri hiçbir şey eşleşmediğinde nil döndürür.
Yakalama grupları
Parantezler yakalar. FindStringSubmatch tüm eşleşmeyi 0. indekste, ardından her grup için bir girdi döndürür:
Sonucu indekslemeden önce her zaman nil kontrolü yapın; eşleşme yoksa m[1] panic olur.
(?:...) yakalamadan gruplar; alternatif ya da tekrar için: (?:ab)+. Adlı gruplar (?P<name>...) olarak, Go 1.22'den beri ayrıca (?<name>...) olarak yazılır.
Değiştirmek
Grup başvurularıyla ilgili klasik bir tuzak: "$1x", var olmayan 1x adlı bir grup olarak okunur ve boş bir string'e genişler. "${1}x" yazın.
Sabit bir string için strings.ReplaceAll, strings.Contains ve strings.Split bir regexp'ten daha basit ve hızlıdır. Aradığınız metnin sabit bir değeri değil de bir biçimi olduğunda regexp'e başvurun.
Söz dizimi hızlı başvurusu
Go, tanıdık Perl tarzı özellikleri kapsayan RE2 söz dizimini kullanır:
| Söz dizimi | Eşleştiği |
|---|---|
. | yeni satır dışında herhangi bir karakter ((?s) ile yeni satır da) |
\d \w \s | rakam, kelime karakteri [0-9A-Za-z_], boşluk (yalnızca ASCII) |
\D \W \S | olumsuzları |
[abc] [^abc] [a-z] | karakter sınıfları |
\pL \p{Greek} | Unicode sınıfları: herhangi bir harf, herhangi bir Yunan karakteri |
* + ? {n,m} | tekrar, açgözlü |
*? +? ?? | tekrar, tembel |
^ $ | metnin başı ve sonu ((?m) ile satırın) |
\b | kelime sınırı (ASCII) |
a|b | alternatif |
(?i) | o noktadan çevreleyen grubun sonuna kadar büyük/küçük harf duyarsız; genellikle desenin başına yazılır |
\d ve \w yalnızca ASCII ile eşleşir. "Herhangi bir dildeki herhangi bir harf" için \pL, herhangi bir Unicode rakamı için \p{Nd} kullanın. regexp.QuoteMeta(s), s içindeki her özel karakteri kaçışlar; kullanıcı girdisinden bir desen oluştururken buna ihtiyacınız olur.
RE2'nin yapamadıkları
Go'nun regexp'i eşleştirmenin girdinin uzunluğuna göre doğrusal zaman almasını garanti eder. Bu garantiyi bozacak özellikler desteklenmez:
- Lookahead ya da lookbehind yok:
(?=...),(?!...),(?<=...),(?<!...)derleme hatasıdır. Go 1.22 adlı gruplar için(?<name>...)'i kabul etmeye başladığından, bir lookbehind artık aşağıdaki programın gösterdiği gibi kafa karıştırıcıinvalid named capturemesajıyla başarısız olur. - Geri başvuru yok: çift harfi eşleştirmek için
(\w)\1mümkün değildir. - Possessive niceleyiciler ya da atomik gruplar yok.
Geçici çözüm neredeyse her zaman aynıdır: ihtiyacınızdan biraz fazlasını yakalayın, sonra Go'da filtreleyin ya da dilimleyin. Karşılığında bir Go regexp'i felaket boyutunda geri izlemeye (catastrophic backtracking) itilemez. Bir PCRE motorunu kısa bir girdide dondurabilen (a+)+$ gibi bir desen burada doğrusal zamanda çalışır; bu, desen ya da girdi dışarıdan geldiğinde önemlidir.
Sık yapılan hatalar
- Bir döngü ya da handler içinde derlemek. Paket seviyesindeki bir değişkene bir kez derleyin.
- Çift tırnaklı desenler.
"\d"geçerli bir Go string'i bile değildir; ters tırnak kullanın. - Doğrulamada çapaları unutmak.
\d{5},"abc123456xyz"içinde eşleşir.^\d{5}$kullanın. - Bir alt eşleşme sonucunu
nilkontrolü olmadan indekslemek. \wya da\b'nin ASCII olmayan metni anlamasını beklemek.\pLgibi Unicode sınıflarını kullanın.- Sabit string'ler için regexp kullanmak.
stringspaketi daha anlaşılır ve daha hızlıdır.
Sıkça Sorulan Sorular
Go'da bir string'in bir regex ile eşleşip eşleşmediği nasıl kontrol edilir?
Deseni regexp.MustCompile ile bir kez derleyin; ters eğik çizgilerin kaçış gerektirmemesi için onu ters tırnaklı ham bir string olarak yazın, sonra re.MatchString(s)'i çağırın. Çapalar (^ ve $) olmadan MatchString, desen string'in herhangi bir yerinde eşleşirse true döndürür.
Go regexp lookahead ve lookbehind destekler mi?
Hayır. Go'nun regexp'i, lookahead, lookbehind ya da geri başvurusu olmayan RE2 söz dizimini kullanır. Karşılığında eşleştirme girdi boyutuna göre doğrusal zamanda çalışır, bu yüzden kötü niyetli bir desen ya da girdi programınızı kilitleyemez. Bunun yerine yakalama grupları ve biraz Go kodu kullanın ya da kontrolü iki regex'e bölün.
regexp.Compile ile regexp.MustCompile arasındaki fark nedir?
Compile derlenmiş deseni ve bir hata döndürür. MustCompile ise geçersiz bir desende bunun yerine panic yapar. Kaynak kodunuzda yazılmış desenler için, genellikle paket seviyesindeki bir değişkende, MustCompile kullanın ki bir yazım hatası başlangıçta başarısız olsun. Kullanıcılardan ya da yapılandırma dosyalarından gelen desenler için Compile kullanın.
Go'da bir regex'ten yakalama grupları nasıl alınır?
- indeksin tüm eşleşme, 1, 2, ... indekslerinin gruplar olduğu bir slice döndüren ya da eşleşme yoksa
nildöndürenFindStringSubmatch'i kullanın. Tüm eşleşmeler içinFindAllStringSubmatch(s, -1)kullanın. Adlı gruplar(?P<year>\d{4}),re.SubexpIndex("year")ile bulunabilir.