مسیر
/
Go
Go
/
برنامه‌ی درسی
/
عبارات باقاعده
عب

عبارات باقاعده در Go

1 تمرین

درباره‌ی عبارات باقاعده

پکیج 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*`)

با استفاده از این تابع، نیازی به رسیدگی به خطا نیست.

Caution

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» را در این مقاله ببینید.

ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود

عبارات باقاعده را یاد بگیرید

تمرین کردن قفل شده است

برای تمرین عبارات باقاعده قفل 2 تمرین دیگر را باز کنید