用 Google BigQuery 中的文字替换正则表达式字符
Posted
技术标签:
【中文标题】用 Google BigQuery 中的文字替换正则表达式字符【英文标题】:Replacing regex characters with their literal in Google BigQuery 【发布时间】:2019-04-03 22:22:10 【问题描述】:我有许多包含密码的 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个例子,可以提供更多 那么你认为第二个是第一个的扩展吗?这种扩展的定义是什么 -passwords are an extension of another
?是的,再举几个例子也有助于理解你的想法:o)
我希望能够将我的密码用作正则表达式来匹配另一个表中的密码,而不会出错。为此,我需要转义导致密码被视为无效正则表达式的所有字符
@PhilippeFisher,您能解释一下为什么使用 REGEXP_CONTAINS 而不是 STRPOS 的原因吗?您只是在寻找子字符串吗?
【参考方案1】:
\\\\\\0
我们可以使用 '\0' 替换匹配的字符串。在它之前添加'\'。使用转义字符,整体替换看起来像 '\\\\\\0
'
regexp_replace(Astr, r'[\.\*\+\?\^\$\\\(\)\|\[\]]', '\\\\\\0')
【讨论】:
以上是关于用 Google BigQuery 中的文字替换正则表达式字符的主要内容,如果未能解决你的问题,请参考以下文章
BigQuery 中的 Google Analytics(分析)站点搜索
使用 Google BigQuery Python 库创建或替换表