Regex - Как захватить "несколько" повторяющихся групп в регулярных выражениях Голанга?
У меня есть следующий текстовый файл, который я хотел бы проанализировать, чтобы получить отдельные поля:
host_group_web = ( )
host_group_lbnorth = ( lba050 lbhou002 lblon003 )
Поля, которые я хотел бы извлечь, выделены жирным шрифтом
- host_group_web = ()
- host_group_lbnorth = (lba505 lbhou002 lblon003)
host_group_web не имеет элементов между (), поэтому эта часть будет игнорироваться
Я назвал первую группу как nodegroup, а элементы между () как узлы
Я читаю файл построчно и сохраняю результаты для дальнейшей обработки.
На Голанге это фрагмент Regex, который я использую:
hostGroupLine := "host_group_lbnorth = ( lba050 lbhou002 lblon003 )"
hostGroupExp := regexp.MustCompile(`host_group_(?P<nodegroup>[[:alnum:]]+)\s*=\s*\(\s*(?P<nodes>[[:alnum:]]+\s*)`)
hostGroupMatch := hostGroupExp.FindStringSubmatch(hostGroupLine)
for i, name := range hostGroupExp.SubexpNames() {
if i != 0 {
fmt.Println("GroupName:", name, "GroupMatch:", hostGroupMatch[i])
}
}
Я получаю следующий вывод, в котором отсутствуют остальные совпадения для узлов с именем group.
GroupName: nodegroup GroupMatch: lbnorth
GroupName: nodes GroupMatch: lba050
Сниппет на детской площадке Голанга
Мой вопрос: как мне получить Regex в Golang, который бы соответствовал группе узлов и всем узлам, которые могут быть в строке, например, lba050 lbhou002 lblon003. Количество узлов будет варьироваться, от 0 - столько же.
1 ответ
Если вы хотите захватить имя группы и все возможные имена узлов, вам следует работать с другим шаблоном регулярных выражений. Этот должен захватить их всех за один раз. Нет необходимости работать с именованными группами захвата, но вы можете, если хотите.
hostGroupExp := regexp.MustCompile(`host_group_([[:alnum:]]+)|([[:alnum:]]+) `)
hostGroupLine := "host_group_lbnorth = ( lba050 lbhou002 lblon003 )"
hostGroupMatch := hostGroupExp.FindAllStringSubmatch(hostGroupLine, -1)
fmt.Printf("GroupName: %s\n", hostGroupMatch[0][1])
for i := 1; i < len(hostGroupMatch); i++ {
fmt.Printf(" Node: %s\n", hostGroupMatch[i][2])
}
Увидеть это в действии на детской площадке
Альтернатива:
Вы также можете работать так, как awk будет выполнять синтаксический анализ: используйте выражение regex p, чтобы разбить строки в токенах и распечатать нужные токены. Конечно, расположение линий должно быть таким же, как приведено в вашем примере.
package main
import (
"fmt"
"regexp"
)
func printGroupName(tokens []string) {
fmt.Printf("GroupName: %s\n", tokens[2])
for i := 5; i < len(tokens)-1; i++ {
fmt.Printf(" Node: %s\n", tokens[i])
}
}
func main() {
// regexp line splitter (either _ or space)
r := regexp.MustCompile(`_| `)
// lines to parse
hostGroupLines := []string{
"host_group_lbnorth = ( lba050 lbhou002 lblon003 )",
"host_group_web = ( web44 web125 )",
"host_group_web = ( web44 )",
"host_group_lbnorth = ( )",
}
// split lines on regexp splitter and print result
for _, line := range hostGroupLines {
hostGroupMatch := r.Split(line, -1)
printGroupName(hostGroupMatch)
}
}
Увидеть это в действии на детской площадке