Поиск n-го вхождения шаблона в строке в SQL (Presto)
Я пишу запрос в Presto SQL с помощью функции regexp_extract
У меня есть строка, которая может выглядеть как в следующих примерах:
'1A2B2C3D3E'
'1A1B2C2D3E'
'1A2B1C2D2E'
Я пытаюсь найти, например, второе вхождение 1 [AE].
Если я попробую
regexp_extract(col, '(1[A-E])(1[A-E])', 2)
Это будет работать для второго примера (и первого, поскольку он ничего не возвращает, поскольку второго вхождения нет). Однако в третьем примере это не получится. Он ничего не возвращает. Я знаю , что это потому , что мое регулярное выражение ищет 1 [AE] , а затем непосредственно на другие 1 [AE].
Итак, я попробовал
regexp_extract(col, '(1[A-E])(.*)(1[A-E])', 3)
Но это тоже не работает. Я не уверен, как я могу объяснить тот факт, что у меня может быть 1A1B2C или 1A2B1C, чтобы найти эту вторую 1. Любая помощь?
2 ответа
Ваш второй шаблон действительно работает в последней версии Trino ( ранее известной как Presto SQL):
WITH t(col) AS (
VALUES
'1A2B2C3D3E',
'1A1B2C2D3E',
'1A2B1C2D2E')
SELECT regexp_extract(col, '(1[A-E])(.*)(1[A-E])', 3)
FROM t
_col0
-------
NULL
1B
1C
(3 rows)
Как отмечали другие, вам не нужны группы захвата для первого совпадения или для, и вы должны использовать ленивый квантификатор, чтобы избежать
.*
с нетерпением сопоставляет все символы между первым и последним вхождением:
WITH t(col) AS (
VALUES
'1A2B2C3D3E',
'1A1B2C2D3E',
'1A2B1C2D2E',
'1A2B1C2D1E')
SELECT regexp_extract(col, '1[A-E].*?(1[A-E])', 1)
FROM t
_col0
-------
NULL
1B
1C
1C
(4 rows)
Вторая группа захвата не нужна
(.*)
чтобы сохранить 2 группы захвата в результате, и вы можете при желании сопоставить разрешенные символы между ними.
Из того, что я прочитал на этой странице, вы также можете рассмотреть возможность использования
regexp_extract_all
чтобы получить все совпадения, как
regexp_extract
возвращает первое совпадение.
Поскольку данные примера состоят из цифры, за которой следует символ AE, вы можете исключить соответствие 1 из класса символов, чтобы предотвратить избыточное соответствие и возврат.
(1[A-E])[02-9A-E]*(1[A-E])
Если использование одной группы захвата для получения второго значения тоже нормально, вы можете использовать
1[A-E][02-9A-E]*(1[A-E])