Oracle регулярное выражение n символов до и после подстроки, исключая пробелы - PullRequest
1 голос
/ 07 апреля 2020

Я хотел бы выбрать 10 символов до и после определенной подстроки из строки в oracle. Если мы рассмотрим содержимое таблицы следующим образом:

with tmp as (
select 'aa bbbb cccc xx ddddd eeeeeee' as main_text,
'xx' as sub_text
from dual
)
select * from dual;

Я хочу получить вывод:
aa bbbb cccc xx ddddd eeeee

Поэтому я хотел бы исключить пробелы и считать 10 до слева и 10 справа от подстроки, которая равна 'xx'.

С пробелами это просто, но без пробелов в одном запросе; Я не могу придумать логи c.

Эксперты, которые могли бы помочь, пожалуйста. Использование Oracle 11g: D

Ответы [ 3 ]

2 голосов
/ 07 апреля 2020

Вы можете использовать REGEXP_SUBSTR и группы захвата для получения подстрок до и после:

with tmp ( main_text, sub_text ) as (
  SELECT 'aa bbbb cccc xx ddddd eeeeeee', 'xx' FROM DUAL
)
SELECT t.*,
       REGEXP_SUBSTR(
         main_text,
         '((\S\s*){0,10})' || sub_text || '((\s*\S){0,10})',
         1,
         1,
         NULL,
         1
       ) AS before_text,
       REGEXP_SUBSTR(
         main_text,
         '((\S\s*){0,10})' || sub_text || '((\s*\S){0,10})',
         1,
         1,
         NULL,
         3
       ) AS after_text
FROM   tmp t;

Какие выходные данные:

MAIN_TEXT                     | SUB_TEXT | BEFORE_TEXT   | AFTER_TEXT  
:---------------------------- | :------- | :------------ | :-----------
aa bbbb cccc xx ddddd eeeeeee | xx       | aa bbbb cccc  |  ddddd eeeee

И если вы хотите убрать пробелы, то:

with tmp ( main_text, sub_text ) as (
  SELECT 'aa bbbb cccc xx ddddd eeeeeee', 'xx' FROM DUAL
)
SELECT t.*,
       REGEXP_REPLACE(
         REGEXP_SUBSTR(
           main_text,
           '((\S\s*){0,10})' || sub_text || '((\s*\S){0,10})',
           1,
           1,
           NULL,
           1
         ),
         '\s+'
       ) AS before_text,
       REGEXP_REPLACE(
         REGEXP_SUBSTR(
           main_text,
           '((\S\s*){0,10})' || sub_text || '((\s*\S){0,10})',
           1,
           1,
           NULL,
           3
         ),
         '\s+'
       ) AS after_text
FROM   tmp t;

Какие выходные данные:

MAIN_TEXT                     | SUB_TEXT | BEFORE_TEXT | AFTER_TEXT
:---------------------------- | :------- | :---------- | :---------
aa bbbb cccc xx ddddd eeeeeee | xx       | aabbbbcccc  | dddddeeeee

дБ <> скрипка здесь

2 голосов
/ 07 апреля 2020

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

select tmp.*,
       regexp_substr(main_text, '.{0,10}' || sub_text || '.{0,10}')
from tmp;

Примечание: Это не возвращает точно то, что вы указываете, потому что это считает пробелы как символ.

Если вы не хотите считать пробелы, вы можете игнорировать их как:

select tmp.*,
       regexp_substr(main_text, '([^ ] *){0,10}' || sub_text || '( *[^ ] *){0,10}')
from tmp;

Здесь - это db <> скрипка.

0 голосов
/ 08 апреля 2020

Спасибо, @ Гордон и @ MT0. Используя идеи обоих ваших решений:

with tmp as (
select
    'aa bbbb cccc xx ddddd eeeeeee' as main_text,
    'xx' as sub_text
from dual
)
select tmp.*,
       regexp_substr(
            main_text, 
            '(([^ ] *){0,10})' || sub_text || '(( *[^ ] *){0,10})'
       ) as plus_minus_ten,
       regexp_substr(
            main_text, 
            '(([^ ] *){0,10})' || sub_text || '(( *[^ ] *){0,10})', 
            1, 
            1, 
            NULL, 
            1 
       ) as before_sub_text,
       regexp_substr(main_text, 
            '(([^ ] *){0,10})' || sub_text || '(( *[^ ] *){0,10})', 
            1, 
            1, 
            NULL,
            3
       ) as after_sub_text
from tmp;
...