Маскировка Teradata - Сохраните все символы в позиции 1,4,8,12,16 .... в строке и замаскируйте оставшиеся символы знаком 'X' - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть требование, где мне нужно замаскировать все, кроме символов в позиции 1,4,8,12,16 .. для строки переменной длины с 'X'

Например:

Input string - 'John Doe'
Output String - 'JXXn xxE'

Пробел между двумя строками должен быть сохранен.

Пожалуйста, помогите или обратитесь за дополнительной информацией, если требуется.

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

Я не мог придумать решение, но затем @JNevill вдохновил меня своей идеей добавить запятую к каждому символу: -)

SELECT
   RegExp_Replace(
      RegExp_Replace(
         RegExp_Replace(inputString, '(.)(.)?(.)?(.)?', '(\1(\2[\3(\4', 2)
                     ,'(\([^ ])', 'X')
                  ,'(\(|\[)')
   ,'this is a test of this functionality' AS inputString

tXXs XX X XeXX oX XhXX fXXXtXXXaXXXy

1-й RegExp_Replace начинается со 2-го символа (сохранить1-й символ как есть) и обрабатывает группы из (до) 4 символов, добавляя либо ( (символы # 1, # 2, # 4, которые должны быть заменены на X, если это не пробел), либо [(символ № 3, без замены), что приводит к:

t(h(i[s( (i(s[ (a( (t[e(s(t( [o(f( (t[h(i(s( [f(u(n(c[t(i(o(n[a(l(i(t[y(

Конечно, это предполагает, что оба символа не существуют во ваших входных данных, в противном случае вам придется выбирать разные.

2-е RegExp_Replace заменяет ( и следующий символ на X, если это не пробел, что приводит к:

tXX[s( XX[ X( X[eXX( [oX( X[hXX( [fXXX[tXXX[aXXX[y(

Теперь осталось несколько ( & [, которыеудалено 3-м RegExp_Replace.

Поскольку я по-прежнему считаю себя новичком в регулярных выражениях, будут лучшие решения: -)

Редактировать:

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

   RegExp_Replace(
      RegExp_Replace(
         RegExp_Replace(inputString, '(.)(.)?(.)?(.)?', '(\1(\2[\3(\4', 2, 0 'c')
                     ,'(\([^ ])', 'X', 1, 0 'c')
                  ,'(\(|\[)', '', 1, 0 'c')
0 голосов
/ 27 апреля 2018

Я думаю, что, возможно, здесь лучше использовать внешнюю функцию, но если это слишком много, вы можете получить хитрость с помощью strtok_split_to_table, xml_agg и regexp_replace, чтобы разорвать строку на части, заменить символы, используя вашикритерии и объедините их вместе:

WITH cte AS (SELECT REGEXP_REPLACE('this is a test of this functionality', '(.)', '\1,') AS fullname FROM Sys_Calendar.calendar WHERE calendar_date = CURRENT_DATE)
SELECT
    REGEXP_REPLACE(REGEXP_REPLACE((XMLAGG(tokenout ORDER BY tokennum) (VARCHAR(200))), '(.) (.)', '\1\2')   , '(.) (.)', '\1\2')
FROM
(
    SELECT 
        tokennum,
        outkey,
        CASE WHEN tokennum = 1 OR tokennum mod 4 = 0 OR token = ' ' THEN token ELSE 'X' END AS tokenout

    FROM TABLE (strtok_split_to_table(cte.fullname, cte.fullname, ',')
        RETURNS (outkey VARCHAR(200), tokennum integer, token VARCHAR(200) CHARACTER SET UNICODE)) AS d
) stringshred
GROUP BY outkey

Это не будет быстрым для большого набора данных, но может быть достаточно в зависимости от того, сколько данных вам нужно обработать.

Разбивкаэто вниз:

WITH cte AS (SELECT REGEXP_REPLACE('this is a test of this functionality', '(.)', '\1,') AS fullname FROM Sys_Calendar.calendar WHERE calendar_date = CURRENT_DATE)

Этот CTE просто добавляет запятую между каждым символом нашей входящей строки, используя эту функцию regexp_replace.Ваше имя будет выглядеть как J,o,h,n, ,D,o,e.Вы можете проигнорировать часть sys_calendar, я просто вставил ее, чтобы она выдавала ровно 1 запись для тестирования.

   SELECT 
        tokennum,
        outkey,
        CASE WHEN tokennum = 1 OR tokennum mod 4 = 0 OR token = ' ' THEN token ELSE 'X' END AS tokenout

    FROM TABLE (strtok_split_to_table(cte.fullname, cte.fullname, ',')
        RETURNS (outkey VARCHAR(200), tokennum integer, token VARCHAR(200) CHARACTER SET UNICODE)) AS d

Этот подзапрос является важным битом.Здесь мы создаем запись для каждого персонажа в вашем имени.strtok_split_to_table выполняет здесь работу, разделяя входящее имя запятой (которое мы добавили в CTE)

Оператор Case просто запускает критерии, заменяя 'X' на правильные позиции (запись 1,или кратное 4, а не пробел).

 SELECT
    REGEXP_REPLACE(REGEXP_REPLACE((XMLAGG(tokenout ORDER BY tokennum) (VARCHAR(200))), '(.) (.)', '\1\2')   , '(.) (.)', '\1\2')

Наконец, мы используем XMLAGG, чтобы объединить множество записей обратно в одну строку в одной записи.Поскольку XMLAGG добавляет пробел между каждым символом, мы должны ударить его пару раз с помощью regexp_replace, чтобы перевернуть эти пробелы в ноль.

Итак ... это некрасиво, но делает свою работу.

Вышеприведенный код выплевывает:

tXXs XX X XeXX oX XhXX fXXXtXXXaXXXy
...