Регулярные выражения в Go (Golang): полное руководство для начинающих
Регулярные выражения (regex) — это мощный инструмент для поиска, извлечения и замены текста по заданным шаблонам. В языке Go (Golang) работа с регулярными выражениями реализована через стандартный пакет regexp. В этой статье мы разберем основы работы с regexp в Go, рассмотрим ключевые функции и приведем практические примеры, которые помогут вам начать использовать регулярные выражения в своих проектах.
Что такое регулярные выражения и зачем они нужны в Go?
Регулярное выражение — это последовательность символов, задающая шаблон для поиска в тексте. Например, вы можете проверить, содержит ли строка email, номер телефона или определенный формат данных. В Go пакет regexp предоставляет функции для компиляции шаблонов, поиска совпадений, замены текста и извлечения подстрок.
Основные возможности regexp:
- Поиск — проверка наличия подстроки, соответствующей шаблону.
- Извлечение — получение всех совпадений или отдельных групп.
- Замена — замена найденных фрагментов на другой текст.
- Валидация — проверка формата строки (email, пароль, URL).
Установка и импорт пакета regexp
Пакет regexp входит в стандартную библиотеку Go, поэтому устанавливать ничего не нужно. Для использования достаточно импортировать его в начале файла:
import (
"fmt"
"regexp"
)
1. Компиляция регулярного выражения: Compile и MustCompile
Первым шагом в работе с регулярными выражениями является компиляция шаблона. В Go есть два основных способа:
regexp.Compile(expr)— возвращает скомпилированное выражение и ошибку, если шаблон некорректен.regexp.MustCompile(expr)— аналогично, но вызывает панику (panic) при ошибке. Удобно для статических шаблонов.
Пример:
package main
import (
"fmt"
"regexp"
)
func main() {
// Используем MustCompile, так как шаблон заведомо корректен
re := regexp.MustCompile(`[a-z]+`)
// Compile с обработкой ошибки
re2, err := regexp.Compile(`[0-9]+`)
if err != nil {
fmt.Println("Ошибка компиляции:", err)
return
}
fmt.Println(re, re2)
}
2. Основные методы поиска и проверки
После компиляции у нас есть объект *regexp.Regexp с набором методов. Рассмотрим самые полезные.
MatchString — проверка на соответствие
Метод MatchString(s string) bool возвращает true, если строка содержит хотя бы одно совпадение с шаблоном.
re := regexp.MustCompile(`go`)
fmt.Println(re.MatchString("golang")) // true
fmt.Println(re.MatchString("python")) // false
FindString — поиск первого совпадения
Возвращает первую подстроку, соответствующую шаблону.
re := regexp.MustCompile(`[0-9]+`)
fmt.Println(re.FindString("Цена: 100 рублей, скидка 20%")) // "100"
FindAllString — поиск всех совпадений
Возвращает срез всех найденных строк. Второй аргумент — максимальное количество совпадений (-1 — все).
re := regexp.MustCompile(`[0-9]+`)
result := re.FindAllString("Цена: 100 рублей, скидка 20%", -1)
fmt.Println(result) // ["100", "20"]
3. Извлечение групп с помощью подвыражений
Круглые скобки в шаблоне создают группы захвата (capturing groups). Метод FindStringSubmatch возвращает срез, где первый элемент — полное совпадение, а последующие — значения групп.
re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
date := "Дата: 2023-12-25"
matches := re.FindStringSubmatch(date)
if len(matches) > 0 {
fmt.Println("Полная дата:", matches[0]) // 2023-12-25
fmt.Println("Год:", matches[1]) // 2023
fmt.Println("Месяц:", matches[2]) // 12
fmt.Println("День:", matches[3]) // 25
}
4. Замена текста: ReplaceAllString и ReplaceAllStringFunc
Метод ReplaceAllString(src, repl string) string заменяет все совпадения на строку repl. В repl можно использовать ссылки на группы: $1, $2 и т.д.
re := regexp.MustCompile(`(\w+)@(\w+)\.(\w+)`)
email := "Мой email: user@example.com"
result := re.ReplaceAllString(email, "$1@***.$3")
fmt.Println(result) // "Мой email: user@***.com"
ReplaceAllStringFunc позволяет задать функцию для замены:
re := regexp.MustCompile(`\d+`)
text := "Числа: 10, 20, 30"
result := re.ReplaceAllStringFunc(text, func(s string) string {
return "[" + s + "]"
})
fmt.Println(result) // "Числа: [10], [20], [30]"
5. Практический пример: валидация email и извлечение данных
Давайте напишем небольшую программу, которая проверяет корректность email и извлекает имя пользователя и домен.
package main
import (
"fmt"
"regexp"
)
func main() {
// Простой шаблон для email (не идеальный, но для примера подойдет)
emailPattern := `^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$`
re := regexp.MustCompile(emailPattern)
emails := []string{
"user@example.com",
"invalid-email",
"john.doe@company.org",
}
for _, email := range emails {
if re.MatchString(email) {
matches := re.FindStringSubmatch(email)
fmt.Printf("Email