Захват повторяющихся групп в GO - PullRequest
0 голосов
/ 22 ноября 2018

Я пытаюсь создать функцию, которая может анализировать строки, состоящие из заглавного слова, за которым следует ноль или более аргументов, которые заключены в двойные кавычки.

Например, каждая из следующих строк:

COPY "filename one" "filename two"
REMOVE "filename"
LIST "x" "y" "z"
DISCONNECT

Результатом должна быть строка (команда), за которой следует строка [] (аргументы внутри кавычек).Я создал следующее регулярное выражение:

re1, _ := regexp.Compile(`([A-Z]+)(?: "([^"]+)")*`)
results := re1.FindAllStringSubmatch(input, -1)

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

Пример моей проблемы: https://play.golang.org/p/W1rE1X4SWf5

"arg1" в этом примере не фиксируется.Чего мне не хватает?

Ответы [ 4 ]

0 голосов
/ 22 ноября 2018

Добавить дополнительную группу захвата.Если вы сделаете это необязательным, дополнительные данные будут пустыми, но совпадение будет работать

re1, _ := regexp.Compile(`^([A-Z]+)(\s"[^"]+")(\s"[^"]+")?(\s"[^"]+")?$`)

Добавить больше (\s"[^"]+")? выражений до необходимого вам максимума.Я положил в два, так как в ваших примерах есть выражение с 3 параметрами

0 голосов
/ 22 ноября 2018

Я думаю, что это может решить вашу проблему

re1, _ := regexp.Compile(`([A-Z]+)(?: *)`)
commandText:=`COPY "filename one" "filename two"`
if re1.Match([]byte(commandText)){
    index:=re1.FindIndex([]byte(commandText))[1]
    commandArgs:=commandText[index:]
    commandArgsRegex,_:=regexp.Compile(`"([^"]+)"`)
    fmt.Println("Command= " , commandText[0:index])
    for i,arg:=range commandArgsRegex.FindAllString(commandArgs,-1){
        fmt.Println("args ", i,"= " , arg)
    }
}else{
    fmt.Println("Failed")
}
0 голосов
/ 22 ноября 2018

Если ваши команды четко определены, имена команд ei всегда в верхнем регистре, а аргументы всегда после команды, тогда более слабое регулярное выражение может просто соответствовать вашему сценарию использования:

re1, _ := regexp.Compile(`([A-Z]+)|(?: "([^"]+)")`)
results := re1.FindAllStringSubmatch(`COMMAND "arg1" "arg2" "arg3"`, -1)

fmt.Println("Command:", results[0][1])
for _, arg := range results[1:] {
    fmt.Println("Arg:", arg[2])
}

Playground

0 голосов
/ 22 ноября 2018

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

Разделение на команды и аргументы можно выполнить с помощью ([A-Z]+)((?: "[^"]+")*) ( demo ):

  • ([A-Z]+) в первой группе вы получите команду
  • ((?: "[^"]+")*), во второй группе вы получите аргументы в кавычках, разделенные пробелами

Затем вы можете использовать FindAllString с "([^"]+)" для извлечения аргументов ( demo ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...