У меня есть много таблиц 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!))