2017-02-09 5 views
2

У меня длинная строка.PL SQL регулярное выражение подстроки

message := 'I loooove my pet animal'; 

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

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

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

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

спасибо.

+0

что, если длина строки 50 Вы заканчиваете с двумя длиной 25 строки, это нормально? –

+0

Нет, я не могу произвольно сломать слова. Мне не нужно сломать целое слово. Мне нужно разделить на две строки с полными словами. – Roshni

+0

Так что, если строка '' Вы Supercalifragilisticexpialidocious '', где вы хотите разбить? Вы разделились на '' Вы - ''? –

ответ

0
  • Сначала вы reverse Строка.

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

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

    j := INSTR(REVERSE(strField), ' ', i/2, i)` 
    
  • Наконец расщепленного I - J (maybe +/- 1 need to test it)

DEMO

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 

ВЫХОД

enter image description here

+0

'i' не звучит правильно, поскольку последний параметр из instr, всегда будет возвращаться 0 – Deltharis

+0

Спасибо. Я попробую. – Roshni

1

Вот общее решение - с возможно более одной входной строки, так и с входами любой длины. Единственное предположение состоит в том, что ни одно слово не может быть более 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. 
Смежные вопросы