sql >> Base de Datos >  >> RDS >> Oracle

eliminar una palabra específica de la cadena

Debido a la falta de soporte para lookbehind/lookahead y límite de palabra(\b ) en la implementación de expresiones regulares de Oracle, parece imposible cumplir con todos los requisitos en un único REGEXP_REPLACE llamar. Especialmente para el caso, señalado por Egor Skriptunoff :coincidencias de patrón, seguidas una por una con un solo separador entre ellas como some some some some ... .

Sin este caso, es posible hacer coincidir todas esas cadenas con esta llamada:

regexp_replace(
  source_string,                                       -- source string
  '([^[:alnum:]]|^)((\d)*some(\d)*)([^[:alnum:]]|$)',  -- pattern
  '\1\5',                                              -- leave separators in place
  1,                                                   -- start from beginning
  0,                                                   -- replace all occurences
  'im'                                                 -- case-insensitive and multiline 
);

Partes del patrón:

(                -- start of Group #1
  [^[:alnum:]]   -- any non-alphanumeric character 
  |              -- or 
  ^              -- start of string or start of line 
)                -- end of Group #1
(                -- start of Group #2
  (              -- start of Group #3 
    \d           -- any digit
  )              -- end of Group #3
  *              -- include in previous group zero or more consecutive digits
  some           -- core string to match
  (              -- start of group #4
    \d           -- any digit
  )              -- end of group #4  
  *              -- include in previous group zero or more consecutive digits
)                -- end of Group #2
(                -- start of Group #5
  [^[:alnum:]]   -- any non-alphanumeric character 
  |              -- or
  $              -- end of string or end of line
)                -- end of Group #5

Debido a que los separadores utilizados para la coincidencia (Grupo n.º 1 y Grupo n.º 5) incluidos en el patrón de coincidencia, se eliminarán de la cadena de origen en caso de coincidencia exitosa, por lo que necesitamos restaurar estas partes especificando en el tercer regexp_replace parámetro.

Con base en esta solución, es posible reemplazar todo, incluso las ocurrencias repetitivas dentro de un ciclo.

Por ejemplo, puede definir una función como esa:

create or replace function delete_str_with_digits(
  pSourceString in varchar2, 
  pReplacePart  in varchar2  -- base string (like 'some' in question)
)
  return varchar2
is
  C_PATTERN_START constant varchar2(100) := '([^[:alnum:]]|^)((\d)*';
  C_PATTERN_END   constant varchar2(100) := '(\d)*)([^[:alnum:]]|$)';

  vPattern         varchar2(4000);
  vCurValue        varchar2(4000);
  vPatternPosition binary_integer;
begin

  vPattern := C_PATTERN_START || pReplacePart || C_PATTERN_END;
  vCurValue := pSourceString;

  vPatternPosition := regexp_instr(vCurValue, vPattern);

  while(vPatternPosition > 0) loop
    vCurValue := regexp_replace(vCurValue, vPattern,'\1\5',1,0,'im');
    vPatternPosition := regexp_instr(vCurValue, vPattern);
  end loop;

  return vCurValue;  

end;

y utilícelo con SQL u otro código PL/SQL:

SELECT 
  delete_str_with_digits(
    'some text, -> awesome <- 123 someone, 3some3
     line of 7 :> some some some some some some some <
222some  another some1? some22 text 0some000', 
    'some'
  )  as result_string
FROM 
  dual

Ejemplo de SQLFiddle