REGEXP Oracle несколько не утверждений - PullRequest
3 голосов
/ 10 марта 2019

У меня есть строка с 4 именами, разделенными запятыми. 3 из 4 имен имеют строгие идентификаторы внутри, а последнее не имеет идентификатора. Порядок имен в строке случайный. Как я могу получить имя без идентификатора, используя oracle REGEXP?

Пример строки: 'a. Name1, b. Name2, Name3, c-f Name4'

строгими идентификаторами являются 'a.', 'b.', 'c-f'

name1, name2 и name4 Я могу получить таким образом:

select 
regexp_substr('a. Name1, b. Name2, Name3, c-f Name4','(^|, )a.[^,]+($|,)') as name1,
regexp_substr('a. Name1, b. Name2, Name3, c-f Name4','(^|, )b.[^,]+($|,)') as name2,
regexp_substr('a. Name1, b. Name2, Name3, c-f Name4','(^|, )c\-f[^,]+($|,)') as name4
from dual

Я хочу получить name3 с использованием чего-то вроде этого:

'(^|, )((NOT("a."))and(NOT("b."))and(NOT("c-f")))([^,]+($|,)'

Но я не знаю, как это сделать с помощью REGEXP. Возможно ли это в Oracle?

Ответы [ 3 ]

2 голосов
/ 10 марта 2019

Это будет соответствовать 3-й обратной ссылке (любой шаблон, заключенный в квадратные скобки).

REGEXP_REPLACE(
   yourStringColumn,
   'a\. (.*), b\. (.*), (.*), c-f (.*)',
   '\3'
)

Шаблон, который я использовал, содержит 4 обратных ссылки, каждая из которых является именем, которое вы ищете.Остальная часть шаблона (вне обратных ссылок) - это фиксированные части шаблона, который вы описали.Просто не забудьте выйти из точки остановки, чтобы она не рассматривалась как подстановочный знак ('\.')

РЕДАКТИРОВАТЬ:

Если они могутв любом порядке, моя лучшая попытка - найти элемент между запятыми (или началом / концом строки), который сам по себе не содержит запятую или пробел (с пробелом, подразумевающим префикс)

SELECT
  regexp_replace(
    'c-f Name1, Name2, b. Name3, a. Name4', 
    '(^|.+, )([^, ]+)($|, .+)',
    '\2'
  )
FROM
  dual
;
0 голосов
/ 11 марта 2019

Я понял, что могу использовать функцию REGEXP_REPLACE несколько раз:

select 
regexp_replace(
regexp_replace(
regexp_replace(
'a. Name1, b. Name2, Name3, c-f Name4',
'(^|, | )a\.[^,]+($|,)'),
'(^|, | )b\.[^,]+($|,)'),
'(^|, | )c\-f[^,]+($|,)') as name3
from dual

Спасибо, MatBailie, за идею использования REGEXP_REPLACE!

0 голосов
/ 10 марта 2019

Должно ли это быть регулярное выражение? Потому что, если это не так, то комбинация SUBSTR + INSTR тоже хорошо справляется.

SQL> with test (col) as
  2    (select 'a. Name1, b. Name2, Name3, c-f Name4' from dual)
  3  select
  4    trim(substr(col, instr(col, '.', 1, 1) + 1,
  5                     instr(col, ',', 1, 1) - instr(col, '.', 1, 1) - 1)) str1,
  6    trim(substr(col, instr(col, '.', 1, 2) + 1,
  7                     instr(col, ',', 1, 2) - instr(col, '.', 1, 2) - 1)) str2,
  8    trim(substr(col, instr(col, ',', 1, 2) + 1,
  9                     instr(col, ',', 1, 3) - instr(col, ',', 1, 2) - 1)) str3,
 10    trim(substr(col, instr(col, 'c-f', 1, 1) + 4)) str4
 11  from test;

STR1  STR2  STR3  STR4
----- ----- ----- -----
Name1 Name2 Name3 Name4

SQL>

[РЕДАКТИРОВАТЬ, согласно комментарию MatBailie]

SQL> with test (col) as
  2    (select 'a. Name1, b. Name2, Name3, c-f Name4' from dual)
  3  select
  4    trim(substr(col, instr(col, 'a.', 1, 1) + 2,
  5                     instr(col, ', b.', 1, 1) - instr(col, 'a.', 1, 1) - 2)) str1,
  6    trim(substr(col, instr(col, 'b.', 1, 1) + 2,
  7                     instr(col, ',', 1, 2) - instr(col, 'b.', 1, 1) - 2)) str2,
  8    trim(substr(col, instr(col, ',', 1, 2) + 1,
  9                     instr(col, ',', 1, 3) - instr(col, ',', 1, 2) - 1)) str3,
 10    trim(substr(col, instr(col, 'c-f', 1, 1) + 4)) str4
 11  from test;

STR1  STR2  STR3  STR4
----- ----- ----- -----
Name1 Name2 Name3 Name4

SQL>

[РЕДАКТИРОВАТЬ # 2]

Поскольку идентификаторы могут быть размещены где угодно, как на счет такого кода?

SQL> with test (col) as
  2    (select 'a. Little foot, c-f Bruce Wayne, Catherine Zeta-Jones, b. Bill White Jr.' from dual),
  3  inter as
  4    (select trim(regexp_substr(col, '[^,]+', 1, level)) str
  5     from test
  6     connect by level <= regexp_count(col, ',') + 1
  7    ),
  8  inter2 as
  9    (select trim(replace(replace(replace(str, 'a.', ''),
 10                                              'b.', ''),
 11                                              'c-f', '')) result,
 12       rownum rn
 13     from inter
 14    )
 15  select max(decode(rn, 1, result)) n1,
 16         max(decode(rn, 2, result)) n2,
 17         max(decode(rn, 3, result)) n3,
 18         max(decode(rn, 4, result)) n4
 19  from inter2;

N1                   N2                   N3                   N4
-------------------- -------------------- -------------------- --------------------
Little foot          Bruce Wayne          Catherine Zeta-Jones Bill White Jr.

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