Замена символов регулярных выражений их литералом в Google BigQuery - PullRequest
0 голосов
/ 04 апреля 2019

У меня есть много таблиц Bigquery, которые содержат пароли.Я пытаюсь найти повторное использование между паролями.Например, я хочу, чтобы можно было найти, когда пароли являются расширением другого

|---------------------|------------------|
|    Password From    |   Password From  |
|       Table 1       |     Table 2      |
|---------------------|------------------|
|      computer       |    computer77    |
|---------------------|------------------|

. Для этого я присоединяюсь к своим таблицам и затем использую функцию REGEXP_CONTAINS (value, regex) где я бы указал WHERE и имел бы REGEXP_CONTAINS(Table1.password, Table2.password) Общий запрос будет выглядеть примерно так (мои пароли хранятся как BYTES):

SELECT *
FROM (
SELECT safe_cast(A.password as STRING) as Astr, safe_cast(B.password as STRING) as Bstr
FROM Passwords.table1 as A
INNER JOIN Passwords.table2 as B
USING (email)
WHERE A.password != B.password)
WHERE (REGEXP_CONTAINS(Astr, Bstr) OR 
       REGEXP_CONTAINS(Bstr, Astr))

Проблема такого подхода заключается в том, что мойПоле пароля содержит символы, которые не экранируются при интерпретации как регулярное выражение.Это дает мне ошибку вроде:

Cannot parse regular expression: no argument for repetition operator: ?

Мой первый подход - просто удалить все проблемные символы:

regexp_replace(Astr, r'[~\[\]?\(\)*\\+]', '')

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

Мое следующее решение - попытаться экранировать все эти символы с помощью одной и той же функции REGEXP_REPLACE.Я проверяю замену следующим запросом:

SELECT SAFE_CAST(A.password as STRING), 
       REGEXP_REPLACE(SAFE_CAST(A.password as STRING), r'[\.\*\+\?\^\$\{\}\(\)\|\[\]]', 'AAAAAAAAAAAAA\\0')
FROM Passwords.yahoo as A
WHERE REGEXP_CONTAINS(SAFE_CAST(A.password as STRING), r'[\.\*\+\?\^\$\{\}\(\)\|\[\]]')

Теперь это почти делает то, что я хочу, где поле переходит от test$ до testAAAAAAAAAAAAA$

Теперь, если я переключаю замену сAAAAAAAAAAAAA\\0 до \\\\0 меняется test$ на test\0.В итоге я хочу, чтобы test$ стал test\$.

Как добавить \ перед всеми .*+?^${}[]() символами, используя функцию REGEXP_REPLACE.

Примеры:

|---------------------|------------------|
|      Original       |   Transformed    |
|---------------------|------------------|
|      test$pp^       |    test\$pp\^    |
|---------------------|------------------|
|      pa$$word1      |    pa\$\$word1   |
|---------------------|------------------|
|      ^^(..)^^       | \^\^\(\.\.\)\^\^ |
|---------------------|------------------|

В конце я хотел бы иметь возможность использовать этот REGEXP_REPLACE для выполнения запросов повторного использования без получения ошибок.Пример:

select *
from(
select A.password, B.password as Bpass, safe_cast(A.password as string) as Astr, safe_cast(B.password as string) as Bstr
from Passwords.Table1 as A
inner join Passwords.Table2  as B
using (email)
where A.password != B.password)
where REGEXP_CONTAINS(Bstr, regexp_replace(Astr, r'[\.\*\+\?\^\$\{\}\(\)\|\[\]]', !REPLACEMENT!)) or REGEXP_CONTAINS(Astr, regexp_replace(Bstr, r'[~\[\]?\(\)*\\+]', !REPLACEMENT!))

1 Ответ

1 голос
/ 04 апреля 2019

\\\\\\0

Мы можем использовать совпадающую строку вместо '\ 0'. Добавьте «\» перед этим. С escape-символами общая замена будет выглядеть как '\\\\\\0'

regexp_replace(Astr, r'[\.\*\+\?\^\$\{\}\(\)\|\[\]]', '\\\\\\0')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...