Oracle SQL regexp_substr поведение извлечения числа - PullRequest
1 голос
/ 23 апреля 2020

В некотором смысле я ответил на свой вопрос, но я пытаюсь лучше понять ответ:

При использовании regexp_substr (в oracle) для извлечения первого вхождения числа (либо однозначные или многозначные), как / почему модификаторы * и + влияют на результаты? Почему + обеспечивает поведение, которое я ищу, а * - нет? * - это мое использование по умолчанию в большинстве регулярных выражений, поэтому я был удивлен, что оно не соответствует моим потребностям.

Например, в следующем:


select test, 
regexp_substr(TEST,'\d') Pattern1,
regexp_substr(TEST,'\d*') Pattern2, 
regexp_substr(TEST,'\d+') Pattern3
from (
select '123 W' TEST from dual
union
select 'W 123' TEST from dual
);

использование regexp_substr(TEST,'\d*') возвращает нулевое значение для ввода «W 123» - поскольку в строке существует ноль или более цифр, меня это поведение смущает. Я также запутался, почему он работает со строкой «123 W»

Насколько я понимаю, * означает ноль или более вхождений элемента, которому он следует, а + означает 1 или более вхождений предыдущий элемент. В примере, приведенном для pattern2 [\d*], почему он успешно захватывает "123" из "123 W", но он не берет 123 из "W 123", поскольку существует ноль или более вхождений di git, они просто не не существует в начале строки. Существуют ли дополнительные [подразумеваемые] логики c, связанные с использованием *?

Примечание: Я некоторое время оглядывался, пытаясь найти похожие вопросы, которые помогли мне захватить «123» из «W 123», но ближе всего я нашел варианты regexp_replace, которые не соответствовали бы моим потребностям.

Ответы [ 2 ]

1 голос
/ 23 апреля 2020

Таким образом, regexp_count указывает на наличие четырех подстрок, соответствующих шаблону \ d *. Третьим из них является «123». Подразумевается, что первое и второе являются производными от W и пробела, и у вас есть результат нулевой длины, который «потребляет» один символ исходной строки.

select test, 
    regexp_count(TEST,'\d*') Pattern2_c, 
    regexp_substr(TEST,'\d*') Pattern2,
    regexp_substr(TEST,'\d*',1,1) Pattern2_1,
    regexp_substr(TEST,'\d*',1,2) Pattern2_2,
    regexp_substr(TEST,'\d*',1,3) Pattern2_3,
    regexp_substr(TEST,'\d*',1,4) Pattern2_4
 from (select '123 W' TEST from dual
    union
    select 'W 123' TEST from dual
    );

Oracle имеет странный что-то о строках нулевой длины и нулевых значениях.

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

1 голос
/ 23 апреля 2020

Подумав, это действительно имеет смысл. Шаблон \d* говорит, что соответствует любому числу ноль или более раз. Проблема здесь в том, что начало строки всегда будет соответствовать этому шаблону из-за нуля или более раз.

Если строка начинается с числа, то она будет включать эти числа, поэтому, учитывая 123 W , образец соответствует 123. Однако, учитывая шаблон W 123, шаблон также совпадает в начале, но он совпадает с 0 символами. Вот почему вы получаете NULL результат.

Это обычное регулярное выражение, а не Oracle. Вы должны быть осторожны с квантификатором *.

Вот два примера скриптового выражения, чтобы проиллюстрировать это, используя строку W 123:

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