Подберите повторяющиеся шаблоны, которые последовательно разделяются запятой или пробелом в golang - PullRequest
0 голосов
/ 25 июня 2019

Я пытаюсь проанализировать несколько тегов в одном строковом литерале.такие как name=testName, key=testKey, columns=(c1, c2, c3), и я мог бы рассмотреть возможность добавить больше тегов с другим синтаксисом в этой строке в ближайшем будущем.Поэтому естественно изучить регулярное выражение для его реализации.

относительно синтаксиса: допустимый:

`name=testName,key=testKey`
`name=testName, key=testKey`
`name=testName key=testKey`
`name=testName    key=testKey`
`name=testName key=testKey columns=(c1 c2 c3)`
`name=testName key=testKey columns=(c1, c2, c3)`
`name=testName, key=testKey, columns=(c1 c2 c3)`

недействительный:

`name=testName,, key=testKey`  (multiple commas in between)
`name=testName, key=testKey,`  (end with a comma)
`name=testName, key=testKey, columns=(c1,c2 c3)` u can only use comma or whitespace consistently inside columns, the rule applies to the whole tags as well. see below
`name=testName, key=testKey columns=(c1,c2,c3)`

Я придумываю весь шаблон какэто:

((name=\w+|key=\w+)+,\s*)*(name=\w+|key=\w+)+

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

patternName :=  regexp.MustCompile(`name=\w+`)
patternKey := regexp.MustCompile(`key=\w+`)
pattern = ((patternName|patternKey)+,\s*)*(patternName|patternKey)+

, учитывая, что я добавлю больше тегов, весь шаблон определенно станет больше и уродливее.Есть ли какой-нибудь элегантный способ, как комбинированный?

1 Ответ

1 голос
/ 25 июня 2019

Да, то, что вы хотите, возможно. тип regexp.Regexp имеет метод String(), который создает строковое представление. Таким образом, вы можете использовать это для объединения регулярных выражений:

patternName :=  regexp.MustCompile(`name=\w+`)
patternKey := regexp.MustCompile(`key=\w+`)
pattern = regexp.MustCompile(`((`+patternName.String()+`|`+patternKey.String()+`)+,\s*)*(`+patternName.String()+`|`+patternKey.String()`+`)+`)

Может быть сокращено (хотя и менее эффективно) с помощью fmt.Sprintf:

pattern = regexp.MustCompile(fmt.Sprintf(`((%s|%s)+,\s*)*(%s|%s)+`, patternName, patternKey, patternName, patternKey)

Но то, что это возможно, не означает, что вы должны это делать ...

Ваши конкретные примеры будут гораздо легче обрабатывать с использованием стандартных методов анализа текста, таких как strings.Split или strings.FieldsFunc и т. Д. Учитывая предоставленные вами примеры входных данных, я бы сделал это следующим образом:

  1. Разделить на пробел / запятая
  2. Разделите каждый результат на знак равенства.
  3. Проверка правильности названий ключей (name и / или key)

Этот код будет намного легче читать, и он будет выполняться, вероятно, в сотни или тысячи раз быстрее, чем регулярное выражение. Этот подход также легко подходит для потоковой обработки, что может быть большим преимуществом, если вы обрабатываете сотни и более записей и не хотите использовать много памяти. (Регулярное выражение также может быть сделано для этого, но оно еще менее читабельно).

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