ЗАМЕНА не находит все вхождения - PullRequest
1 голос
/ 31 января 2020

Столкнулся с этим неожиданным поведением при написании кода для синтаксического анализа; -ограниченные списки в столбце SQL.

На этом этапе я заменяю только случаи, которые окружены разделителями, чтобы избежать ложные срабатывания. Без разделителей замена «Алиса» в «Алиса; Боб; Алиса; Алиса в стране чудес; Чарль ie» приведет к «Боб; в стране чудес; Чарль ie».

Код для воспроизведения:

SELECT REPLACE('Alice;Alice;Alice;Alice;Alice;Alice',';Alice;',';Bob;')

Это 6 повторений Алисы, 4 из которых окружены разделителями. Ожидаемый результат:

Alice;Bob;Bob;Bob;Bob;Alice

Фактический результат:

Alice;Bob;Alice;Bob;Alice;Alice

Почему 3-й и 5-й Алисы не были заменены?

Моя теория такова, что когда REPLACE находит "; Алиса;» во второй позиции он «резервирует» этот блок текста, так что следующий, 3-й «; Алиса;», который перекрывается со 2-м на один символ, недоступен для ЗАМЕНЫ в качестве совпадения. Логично, потому что ЗАМЕНА первого найденного события может заменить его на что-либо вообще; например, если он заменил его на "# Alice #", тогда 3-й "; Alice;" теперь будет "#Alice;" - нет совпадения.

В этом случае REPLACE фактически не меняет ";" разделяется 2-м и 3-м экземплярами: но внутренне функция REPLACE осторожна и просто перемещается за последний символ 2-й Алисы. И то же самое происходит с 4-м и 5-м вхождениями.

Обходной путь - обернуть ЗАМЕНУ в WHILE, пока строка поиска больше не будет найдена.

У кого-нибудь есть лучшее объяснение или обходной путь

Ответы [ 2 ]

1 голос
/ 31 января 2020

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

SELECT 
REPLACE(
    REPLACE(
        REPLACE('Alice;Alice;Alice;Alice;Alice;Alice',';',';;')  -- First, make your delimiter a double colon so it can be independently consumed
        ,';Alice;',';Bob;'                                      -- Then, search as your initial idea
    )
,';;',';'                                                       -- Finally, revert to single-length delimiters
)

Результат:

Алиса; Боб; Боб; Боб; Боб; Боб Алиса

0 голосов
/ 31 января 2020

Вот визуальное представление двух совпадений ;Alice;, которые будут заменены на ;Bob;:

enter image description here

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