پکیج regexp از عبارتهای باقاعده در Go پشتیبانی میکند.
نحوهی نگارش عبارتهای باقاعدهای که پذیرفته میشود، همان روش کلی است که در Perl، Python و زبانهای دیگر به کار میرود.
هم الگوهای جستوجو و هم متنهای ورودی به صورت UTF-8 تفسیر میشوند.
وقتی از بکتیک (`) برای ساختن رشته استفاده میکنید، بکاسلشها (\) معنای خاصی ندارند و آغاز کاراکترهای خاصی مثل تب \t یا خط جدید \n را نشان نمیدهند:
"\t\n" // regular string literal with 2 characters: a tab and a newline
`\t\n`// raw string literal with 4 characters: two backslashes, a 't', and an 'n'
به همین دلیل، برای ساختن عبارتهای باقاعده استفاده از بکتیک مطلوب است، چون یعنی نیازی به اسکیپ کردن بکاسلشها نداریم:
"\\" // string with a single backslash
`\\` // string with 2 backslashes
RegExp
برای استفاده از یک عبارت باقاعده، اول باید الگوی رشتهای را کامپایل کنیم.
کامپایل در اینجا یعنی گرفتن الگوی رشتهای عبارت باقاعده و تبدیل آن به یک نمایش داخلی که کار کردن با آن آسانتر است.
فقط لازم است هر الگو را یک بار کامپایل کنیم؛ بعد از آن میتوانیم نسخهی کامپایلشدهی عبارت باقاعده را بارها به کار ببریم.
نوع regexp.Regexp یک عبارت باقاعدهی کامپایلشده را نمایش میدهد.
میتوانیم یک الگوی رشتهای را با تابع regexp.Compile به یک regexp.Regexp کامپایل کنیم.
اگر کامپایل شکست بخورد، این تابع nil و یک خطا برمیگرداند:
re, err := regexp.Compile(`(a|b)+`)
fmt.Println(re, err) // => (a|b)+ <nil>
re, err = regexp.Compile(`a|b)+`)
fmt.Println(re, err) // => <nil> error parsing regexp: unexpected ): `a|b)+`
تابع MustCompile جایگزین راحتتری برای Compile است:
re = regexp.MustCompile(`[a-z]+\d*`)
با استفاده از این تابع، نیازی به رسیدگی به خطا نیست.
MustCompile را فقط وقتی باید به کار برد که مطمئن باشیم الگو کامپایل میشود، چون در غیر این صورت برنامه panic میکند.
۱۶ متد از Regexp وجود دارد که یک عبارت باقاعده را مطابقت میدهند و متن مطابقتشده را مشخص میکنند.
نام این متدها با این عبارت باقاعده مطابقت داده میشود:
Find(All)?(String)?(Submatch)?(Index)?
All وجود داشته باشد، این روتین مطابقتهای متوالی و بدون همپوشانی کل عبارت را پیدا میکند.String وجود داشته باشد، آرگومان یک رشته است؛ در غیر این صورت یک اسلایس بایت است؛ مقادیر بازگشتی بهتناسب تنظیم میشوند.Submatch وجود داشته باشد، مقدار بازگشتی یک اسلایس است که زیرمطابقتهای متوالی عبارت را مشخص میکند.Index وجود داشته باشد، مطابقتها و زیرمطابقتها با جفتهای اندیس بایت در رشتهی ورودی مشخص میشوند.همچنین متدهایی برای این کارها وجود دارد:
در مجموع، پکیج regexp بیش از ۴۰ تابع و متد تعریف میکند.
در ادامه استفاده از چند متد را نشان میدهیم.
برای جزئیات این توابع و توابع دیگر، به مستندات API مراجعه کنید.
MatchString
متد MatchString گزارش میدهد که آیا یک رشته شامل مطابقتی از یک عبارت باقاعده هست یا نه.
re = regexp.MustCompile(`[a-z]+\d*`)
b = re.MatchString("[a12]") // => true
b = re.MatchString("12abc34(ef)") // => true
b = re.MatchString(" abc!") // => true
b = re.MatchString("123 456") // => false
FindString
متد FindString رشتهای را برمیگرداند که متن چپترین مطابقت عبارت باقاعده را در خود دارد.
re = regexp.MustCompile(`[a-z]+\d*`)
s = re.FindString("[a12]") // => "a12"
s = re.FindString("12abc34(ef)") // => "abc34"
s = re.FindString(" abc!") // => "abc"
s = re.FindString("123 456") // => ""
FindStringSubmatch
متد FindStringSubmatch اسلایسی از رشتهها را برمیگرداند که متن چپترین مطابقت عبارت باقاعده و، در صورت وجود، مطابقتهای زیرعبارتهای آن را در خود دارد.
از این متد میتوان برای شناسایی رشتههای منطبق با گروههای ثبت استفاده کرد.
مقدار بازگشتی nil یعنی مطابقتی وجود ندارد.
re = regexp.MustCompile(`[a-z]+(\d*)`)
sl = re.FindStringSubmatch("[a12]") // => []string{"a12","12"}
sl = re.FindStringSubmatch("12abc34(ef)") // => []string{"abc34","34"}
sl = re.FindStringSubmatch(" abc!") // => []string{"abc",""}
sl = re.FindStringSubmatch("123 456") // => <nil>
ReplaceAllString
متد re.ReplaceAllString(src,repl) نسخهای از src را برمیگرداند که در آن مطابقتهای عبارت باقاعدهی re با رشتهی جایگزین repl جایگزین شدهاند.
re = regexp.MustCompile(`[a-z]+\d*`)
s = re.ReplaceAllString("[a12]", "X") // => "[X]"
s = re.ReplaceAllString("12abc34(ef)", "X") // => "12X(X)"
s = re.ReplaceAllString(" abc!", "X") // => " X!"
s = re.ReplaceAllString("123 456", "X") // => "123 456"
Split
متد re.Split(s,n) متن s را به زیررشتههایی که با عبارت از هم جدا شدهاند میبُرد و اسلایسی از زیررشتههای میان این مطابقتهای عبارت را برمیگرداند.
مقدار n بیشترین تعداد زیررشتههایی را که بازگردانده میشوند تعیین میکند.
اگر n<0 باشد، متد همهی زیررشتهها را برمیگرداند.
re = regexp.MustCompile(`[a-z]+\d*`)
sl = re.Split("[a12]", -1) // => []string{"[","]"}
sl = re.Split("12abc34(ef)", 2) // => []string{"12","(ef)"}
sl = re.Split(" abc!", -1) // => []string{" ","!"}
sl = re.Split("123 456", -1) // => []string{"123 456"}
پیادهسازی regexp که این پکیج ارائه میدهد، تضمین میشود که در زمانی خطی نسبت به اندازهی ورودی اجرا شود.
پکیج regexp عبارتهای باقاعدهی RE2 را پیادهسازی میکند (به جز \C).
نحوهی نگارش آن تا حد زیادی با PCRE («عبارت باقاعدهی سازگار با Perl») سازگار است، اما تفاوتهایی هم دارد.
برای جزئیات، بخش «Caveat» را در این مقاله ببینید.