如何在标准SQL中使用Unicode规范化删除变音符号(如Accents)?

时间:2018-01-29 20:02:43

标签: unicode google-bigquery

我们如何使用新的normalize函数从BigQuery中删除字符串中的变音符号,例如:

$cardfrom

结果:

café

1 个答案:

答案 0 :(得分:6)

简答

在了解了normalize正在做什么后,实际上非常简单:

WITH data AS(
  SELECT 'Ãâíüçãõ' AS text
)

SELECT
  REGEXP_REPLACE(NORMALIZE(text, NFD), r'\pM', '') nfd_result,
  REGEXP_REPLACE(NORMALIZE(text, NFKD), r'\pM', '') nfkd_result
FROM data

结果:

Row   nfd_result    nfkd_result  
1     Aaiucao       Aaiucao  

您可以使用“NFD”或“NFKD”选项,并且在大多数情况下,它应该可以使用(您仍然应该了解两个选项之间的差异,以便更好地处理您的数据)。

更完整的答案

基本上 normalize 的作用是将字符串中的所有unicode转换为其规范等价物(或兼容形式),以便我们有相同的比较参考(现在理解这已经需要了解一些概念)。

关键是,unicode不仅建立了数字(它们的代码点由U +表示)和它们的字形之间的映射,而且还建立了这些点之间如何相互作用的一些规则。

例如,让我们采用字形á

我们这个角色没有一个unicode。我们实际上可以将其表示为U+00E1或类似U+0061U+0301,它是a´的unicodes。

叶氏! Unicode的定义方式使得您可以组合字符和变音符号,并通过一个接一个地排序来表示它们的并集。

事实上,您可以使用combining diacritics在Unicode中使用online conversor

enter image description here

Unicode定义了这些类型的字符,它们可以通过使用一个聪明而简单的想法将自己与变音符号precomposed characters结合起来:未预先组合的字符具有所谓的0(零)组合类;可以组合的点接收正组合类(例如,´具有类230),用于断言应该如何表示最终字形。

这很酷但最终会产生一个问题,这个问题解释了我们从一开始就讨论的函数 normalize :如果我们读取两个字符串,一个是unicode U+0061U+0301和其他字符串使用U+00E1á),它们应被视为等效!事实上,它是以不同方式表示的相同字形。

这正是normalize正在做的事情。 Unicode为每个字符定义了一个规范形式,这样,当规范化时,最终结果应该是这样的,如果我们有两个字符串,它们具有相同字形的不同代码点,我们仍然可以看到它们相等。

嗯,我们如何规范化代码点基本上有两种可能性:个不同的unicodes组合成一个(在我们的示例中,这会将U+0061U+0301转换为{{1}或者我们可以分解(这将是另一种方式,将U+00E1转换为U+00E1)。

在这里你可以更清楚地看到它:

enter image description here

NF表示canonical equivalent。 NFC意味着检索规范复合字符(联合); NFD是相反的,分解了角色。

您可以在BigQuery中使用此信息:

U+0061U+0301

结果如何:

enter image description here

请注意,WITH data AS( SELECT 'Amélie' AS text ) SELECT text, TO_CODE_POINTS(NORMALIZE(text, NFC)) nfc_result, TO_CODE_POINTS(NORMALIZE(text, NFD)) nfd_result FROM data 列还有一个代码点。到目前为止,您已经知道这是什么了:nfd´分开。

如果你阅读了 normalize 的BigQuery文档,你会发现它也支持NFKC和NFKD类型。这种类型(字母 K )不是通过规范等价而是通过“兼容性”来规范化,也就是说,它将一些字符分解为其成分字母,而不仅仅是变音符号:

enter image description here

字母e(与ffi不同。这种类型的字符称为ligature)也由构成它的字母分解(因此ffi可能会失去等同性)对于某些应用程序,与ffi不同,因此名称兼容性形式)。

现在我们知道如何将字符分解为主字形,然后是变音字符,我们可以使用仅匹配它们从字符串中删除(由表达式regex完成它只与diacritics标记匹配):

\pM

这几乎是(希望) normalize 函数以及它如何用于删除变音符号。感谢用户sigpwned及其对this question的回答,我找到了所有这些信息。当我尝试它并且它没有完成工作时我决定研究这些方法背后的一些理论,并想把它写下来:)。希望它对更多人有用,因为它绝对适合我。