2016-07-25 5 views
1

У меня есть строка с двумя ключевыми словами: «ТЕКУЩЕЕ ИМЯ (S)» и «NEW NAME (S)», и каждое из этих ключевых слов сопровождается кучей слов. Я хочу извлечь эти слова из этих ключевых слов. Выяснить с помощью кода:Golang regexp для сопоставления нескольких шаблонов между ключевыми парами

s := `"CURRENT NAME(S) 
Name1, Name2",,"NEW NAME(S) 
NewName1,NewName2"` 
    re := regexp.MustCompile(`"CURRENT NAME(S).*",,"NEW NAME(S).*"`) 

    segs := re.FindAllString(s, -1) 
    fmt.Println("segs:", segs) 

    segs2 := re.FindAllStringSubmatch(s, -1) 
    fmt.Println("segs2:", segs2) 

Как вы можете видеть, строка имеет вход. «Name1, Name2» - это текущий список имен, а «NewName1, NewName2» - это новый список имен. Я хочу извлечь эти два списка. Эти два списка разделяются запятой. Каждое из ключевых слов начинается с двойной кавычки и заканчивается, когда заканчивается их соответствующая двойная кавычка.

Каким образом можно использовать регулярное выражение, чтобы программа могла печатать «Name1, Name2» и «NewName1,NewName2»?

+0

Проверьте [это демо] (https://play.golang.org/p/BuU54evLzJ), похоже, что вы ищете? –

+0

Да, да. Благодарю. вы должны были сделать это как ответ, а не комментарий. –

+0

Да, я понял это сейчас :) Большое спасибо. –

ответ

1

Проблема с вашим регулярным выражением состоит в том, что строка ввода содержит символы новой строки, а . в Re rexx Go не соответствует новой строке. Другая проблема заключается в том, что .* - это жадный шаблон и wil l соответствует столько символов, сколько может до последнего второго ключевого слова. Кроме того, вам нужно избежать скобок в шаблоне регулярного выражения, чтобы соответствовать буквальным символам ( и ).

Лучший способ решить проблему заключается в изменении .* в шаблон [^"]* инвертированный характер класса и поместить его внутри пары не спасся ( и ) сформировать захватывая группу (конструкцию, чтобы получить submatches из матча).

Вот Go demo:

package main 

import (
    "fmt" 
    "regexp" 
) 

func main() { 
    s := `"CURRENT NAME(S) 
Name1, Name2",,"NEW NAME(S) 
NewName1,NewName2"` 
    re := regexp.MustCompile(`"CURRENT NAME\(S\)\s*([^"]*)",,"NEW NAME\(S\)\s*([^"]*)"`) 

    segs2 := re.FindAllStringSubmatch(s,-1) 
    fmt.Printf("segs2: [%s; %s]", segs2[0][1], segs2[0][2]) 
} 

Теперь, регулярное выражение соответствует:

  • "CURRENT NAME\(S\) - это символьная строка «ТОК NAME (S)`
  • \s* - ноль или более пробелы
  • ([^"]*) - Группа 1, захватывающая символы 0+, отличные от "
  • ",,"NEW NAME\(S\) - строка литералов ",,"NEW NAME(S)
  • \s* - ноль или больше пробельные
  • ([^"]*) - Группа 2 перехвата 0+, кроме "
  • " символов - буквального "
1

Если ваш вход не изменяется, самым простым способом было бы использовать подматрицы (группы). Вы можете попробовать что-то вроде этого:

// (?s) is a flag that enables '.' to match newlines 
var r = regexp.MustCompile(`(?s)CURRENT NAME\(S\)(.*)",,"NEW NAME\(S\)(.*)"`) 
fmt.Println(r.MatchString(s)) 
m := r.FindSubmatch([]byte(s)) // FindSubmatch requires []byte 

for _, match := range m { 
    s := string(match) 
    fmt.Printf("Match - %d: %s\n", i, strings.Trim(s, "\n")) //remove the newline 
} 

Выход: (Обратите внимание, что первый матч вся строка ввода, поскольку она полностью соответствует регулярному выражению (https://golang.org/pkg/regexp/#Regexp.FindSubmatch)

Match - 0: CURRENT NAME(S) 
Name1, Name2",,"NEW NAME(S) 
NewName1,NewName2" 
Match - 1: Name1, Name2 
Match - 2: NewName1,NewName2 

Пример: https://play.golang.org/p/0cgBOMumtp

+0

Существует также FindStringSubmatch, который берет строку и возвращает кусочек строк. – nussjustin

+0

Это не сработает, если во входной строке есть 2 или более пар ключевых слов. –

0

для фиксированного формата как и в примере, вы также можете избежать регулярных выражений и выполнять явный синтаксический анализ, как в этом примере - https://play.golang.org/p/QDIyYiWJHt:

 
package main 

import (
    "fmt" 
    "strings" 
) 

func main() { 
    s := `"CURRENT NAME(S) 
Name1, Name2",,"NEW NAME(S) 
NewName1,NewName2"` 

    names := []string{} 
    parts := strings.Split(s, ",,") 
    for _, part := range parts { 
     part = strings.Trim(part, `"`) 
     part = strings.TrimPrefix(part, "CURRENT NAME(S)") 
     part = strings.TrimPrefix(part, "NEW NAME(S)") 
     part = strings.TrimSpace(part) 
     names = append(names, part) 
    } 
    fmt.Println("Names:") 
    for _, name := range names { 
     fmt.Println(name) 
    } 
} 

Выход:

 
Names: 
Name1, Name2 
NewName1,NewName2 

Он использует несколько строк кода, но может сделать это легче понять логику обработки на первый взгляд.

Смежные вопросы