Подстрока регулярного выражения PL SQL



У меня есть длинная строка.



message := 'I loooove my pet animal';


Эта строка длиной в 23 символа. Если message больше, чем 15 символов, мне нужно найти длину message, где я могу разбить строку на 2 строки. Например, в этом случае



message1 := 'I loove my'
message2 := 'pet animal'


По существу, он должен найти положение целого слова в предыдущем до 15 символов и разбить исходную строку на 2 в этой точке.



Пожалуйста, дайте мне идеи, как я могу это сделать.

Спасибо.

620   2  

2 ответов:

  • Сначала ты реверс струна.

    SELECT REVERSE(strField) FROM DUAL;
    
  • Затем вы вычисляете длину i = length(strField).

  • Затем найдите первый пробел после середины

    j := INSTR( REVERSE(strField), ' ', i / 2,  i)`
    
  • Наконец-то разделен i-j (maybe +/- 1 need to test it)

Демо

WITH parameter (id, strField) as (
    select 101, 'I loooove my pet animal' from dual union all
    select 102, '1992 was a great year for - make something up here as needed' from dual union all
    select 103, 'You are Supercalifragilisticexpialidocious' from dual  
), prepare (id, rev, len, middle) as (
    SELECT id, reverse(strField), length(strField), length(strField) / 2
    FROM parameter
)    
SELECT p.*, l.*, 
       SUBSTR(strField, 1, len -  INSTR(rev, ' ', middle)) as first, 
       SUBSTR(strField, len -  INSTR(rev, ' ', middle) + 2, len) as second
FROM parameter p
JOIN prepare l
  ON p.id = l.id

Вывод

Введите описание изображения здесь

Вот общее решение-возможно, с более чем одной входной строкой и с входами любой длины. Единственное предположение состоит в том, что ни одно слово не может содержать более 15 символов и что все, что находится между двумя пробелами, считается словом. Если "слово" может содержать более 15 символов, то решение может быть адаптировано, но в самом требовании должно быть указано, каков желаемый результат в таком случае.

Я составляю две входные строки в CTE (вверху) - это не часть решение, это просто для тестирования и иллюстрации. Я также написал это в обычном SQL - нет необходимости в коде PL/SQL для этого типа проблемы. Обработка набора (вместо одной строки за раз) должна привести к гораздо лучшему выполнению.

Подход состоит в том, чтобы определить расположение всех пространств (я добавляю и добавляю пробел к каждой строке, поэтому мне не придется иметь дело с исключениями для первой и последней подстроки); затем я решаю, в рекурсивном подзапросе, где каждая "максимальная" подстрока должна быть определена. начало и где оно должно заканчиваться; и тогда вывод подстрок тривиален. Я использовал рекурсивный запрос, который должен работать в Oracle 11.1 (или 11.2 с синтаксисом, который я использовал, с именами столбцов в объявлениях CTE - он может быть легко изменен для работы в 11.1). В Oracle 12 было бы проще переписать ту же идею, используя MATCH_RECOGINZE.

with
     inputs ( id, str ) as (
       select 101, 'I loooove my pet animal' from dual union all
       select 102, '1992 was a great year for - make something up here as needed' from dual
     ),
     positions ( id, pos ) as (
       select id, instr(' ' || str || ' ', ' ', 1, level)
       from   inputs
       connect by level <= length(str) - length(replace(str, ' ')) + 2
              and prior id = id
              and prior sys_guid() is not null
     ),
     r ( id, str, line_number, pos_from, pos_to ) as (
       select id, ' ' || str || ' ', 0, null, 1
         from inputs
       union all
       select r.id, r.str, r.line_number + 1, r.pos_to,
              ( select max(pos)
                from   positions 
                where id = r.id and pos - r.pos_to between 1 and 16
              )
         from r
         where pos_to is not null
     )
select id, line_number, substr(str, pos_from + 1, pos_to - pos_from - 1) as line_text
from   r
where  line_number > 0 and pos_to is not null
order by id, line_number
;

Вывод :

  ID LINE_NUMBER LINE_TEXT
---- ----------- ---------------
 101           1 I loooove my
 101           2 pet animal
 102           1 1992 was a
 102           2 great year for
 102           3 - make
 102           4 something up
 102           5 here as needed

7 rows selected.

Comments

    Ничего не найдено.