我有以下字符串:
brasília
我需要转换为:
brasilia
没有'口音!
我怎么能在BigQuery上做?
谢谢!
请尝试以下快速简单的选项:
#standardSQL
WITH lookups AS (
SELECT
'ç,æ,œ,á,é,í,ó,ú,à,è,ì,ò,ù,ä,ë,ï,ö,ü,ÿ,â,ê,î,ô,û,å,ø,Ø,Å,Á,À,Â,Ä,È,É,Ê,Ë,Í,Î,Ï,Ì,Ò,Ó,Ô,Ö,Ú,Ù,Û,Ü,Ÿ,Ç,Æ,Œ,ñ' AS accents,
'c,ae,oe,a,e,i,o,u,a,e,i,o,u,a,e,i,o,u,y,a,e,i,o,u,a,o,O,A,A,A,A,A,E,E,E,E,I,I,I,I,O,O,O,O,U,U,U,U,Y,C,AE,OE,n' AS latins
),
pairs AS (
SELECT accent, latin FROM lookups,
UNNEST(SPLIT(accents)) AS accent WITH OFFSET AS p1,
UNNEST(SPLIT(latins)) AS latin WITH OFFSET AS p2
WHERE p1 = p2
),
yourTableWithWords AS (
SELECT word FROM UNNEST(
SPLIT('brasília,ångström,aperçu,barège, beau idéal, belle époque, béguin, bête noire, bêtise, Bichon Frisé, blasé, blessèd, bobèche, boîte, bombé, Bön, Boötes, boutonnière, bric-à-brac, Brontë Beyoncé,El Niño')
) AS word
)
SELECT
word AS word_with_accent,
(SELECT STRING_AGG(IFNULL(latin, char), '')
FROM UNNEST(SPLIT(word, '')) char
LEFT JOIN pairs
ON char = accent) AS word_without_accent
FROM yourTableWithWords
输出是
word_with_accent word_without_accent
blessèd blessed
El Niño El Nino
belle époque belle epoque
boîte boite
Boötes Bootes
blasé blase
ångström angstrom
bobèche bobeche
barège barege
bric-à-brac bric-a-brac
bête noire bete noire
Bichon Frisé Bichon Frise
Brontë Beyoncé Bronte Beyonce
bêtise betise
beau idéal beau ideal
bombé bombe
brasília brasilia
boutonnière boutonniere
aperçu apercu
béguin beguin
Bön Bon
UPDATE
下面是如何将此逻辑打包到SQL UDF中 - 因此可以调用accent2latin(word)
来制作“魔法”
#standardSQL
CREATE TEMP FUNCTION accent2latin(word STRING) AS
((
WITH lookups AS (
SELECT
'ç,æ,œ,á,é,í,ó,ú,à,è,ì,ò,ù,ä,ë,ï,ö,ü,ÿ,â,ê,î,ô,û,å,ø,Ø,Å,Á,À,Â,Ä,È,É,Ê,Ë,Í,Î,Ï,Ì,Ò,Ó,Ô,Ö,Ú,Ù,Û,Ü,Ÿ,Ç,Æ,Œ,ñ' AS accents,
'c,ae,oe,a,e,i,o,u,a,e,i,o,u,a,e,i,o,u,y,a,e,i,o,u,a,o,O,A,A,A,A,A,E,E,E,E,I,I,I,I,O,O,O,O,U,U,U,U,Y,C,AE,OE,n' AS latins
),
pairs AS (
SELECT accent, latin FROM lookups,
UNNEST(SPLIT(accents)) AS accent WITH OFFSET AS p1,
UNNEST(SPLIT(latins)) AS latin WITH OFFSET AS p2
WHERE p1 = p2
)
SELECT STRING_AGG(IFNULL(latin, char), '')
FROM UNNEST(SPLIT(word, '')) char
LEFT JOIN pairs
ON char = accent
));
WITH yourTableWithWords AS (
SELECT word FROM UNNEST(
SPLIT('brasília,ångström,aperçu,barège, beau idéal, belle époque, béguin, bête noire, bêtise, Bichon Frisé, blasé, blessèd, bobèche, boîte, bombé, Bön, Boötes, boutonnière, bric-à-brac, Brontë Beyoncé,El Niño')
) AS word
)
SELECT
word AS word_with_accent,
accent2latin(word) AS word_without_accent
FROM yourTableWithWords
值得一提的是,你所要求的是unicode text normalization的简化案例。许多语言在其标准库中具有此功能(例如,Java)。一个好的方法是插入你的文本BigQuery已经规范化。如果这不起作用 - 例如,因为您需要保留原始文本并且您担心点击BigQuery's row size limit - 那么您需要在查询中动态执行规范化。
一些数据库具有用于查询的各种完整性的Unicode规范化的实现(例如,PostgreSQL's unaccent method,PrestoDB's normalize method)。不幸的是,BigQuery不是其中之一。在撰写本文时,BigQuery中没有文本规范化功能。这个答案的实现有点“滚动你自己的不相干”。当BigQuery发布官方功能时,每个人都应该使用它!
假设您需要在查询中进行规范化(并且Google仍然没有为此提供功能),这些是一些合理的选择。
NORMALIZE
谷歌现在已经推出了NORMALIZE
功能。 (感谢@WillianFuks对标记的评论!)现在这是文本规范化的明显选择。例如:
SELECT REGEXP_REPLACE(NORMALIZE(text), r"\pM", '') FROM yourtable;
这里有一个简短的解释,说明这是如何工作的以及为什么在评论中需要调用REGEXP_REPLACE
。
我已经留下了额外的方法供参考。
REGEXP_REPLACE
and REPLACE
on Content我使用REGEXP_REPLACE
在遗留SQL中实现了仅小写的文本规范化案例。 (标准SQL中的模拟是相当不言而喻的。)我在一个28M行的大表中使用下面的查询对平均长度约为1K的文本字段进行了一些测试:
SELECT id, text FROM
(SELECT
id,
CASE
WHEN REGEXP_CONTAINS(LOWER(text), r"[àáâäåæçèéêëìíîïòóôöøùúûüÿœ]") THEN
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(LOWER(text), 'œ', 'ce'), 'ÿ', 'y'), 'ç', 'c'), 'æ', 'ae'),
r"[ùúûü]", 'u'),
r"[òóôöø]", 'o'),
r"[ìíîï]", 'i'),
r"[èéêë]", 'e'),
r"[àáâäå]", 'a')
ELSE
LOWER(text)
END AS text
FROM
yourtable ORDER BY id LIMIT 10);
与:
WITH lookups AS (
SELECT
'ç,æ,œ,á,é,í,ó,ú,à,è,ì,ò,ù,ä,ë,ï,ö,ü,ÿ,â,ê,î,ô,û,å,ø,ñ' AS accents,
'c,ae,oe,a,e,i,o,u,a,e,i,o,u,a,e,i,o,u,y,a,e,i,o,u,a,o,n' AS latins
),
pairs AS (
SELECT accent, latin FROM lookups,
UNNEST(SPLIT(accents)) AS accent WITH OFFSET AS p1,
UNNEST(SPLIT(latins)) AS latin WITH OFFSET AS p2
WHERE p1 = p2
)
SELECT foo FROM (
SELECT
id,
(SELECT STRING_AGG(IFNULL(latin, char), '') AS foo FROM UNNEST(SPLIT(LOWER(text), '')) char LEFT JOIN pairs ON char=accent) AS foo
FROM
yourtable ORDER BY id LIMIT 10);
平均而言,REGEXP_REPLACE
的实施速度约为2.9秒;基于数组的实现大约运行12.5秒。
REGEXP_REPLACE
on Search Pattern是什么让我想到这个问题我的搜索用例。对于这个用例,我可以规范化我的语料库文本,使其看起来更像我的查询,或者我可以“反规范化”我的查询,使其看起来更像我的文本。以上描述了第一种方法的实现。这描述了第二种的实现。
搜索单个单词时,可以使用REGEXP_MATCH
匹配函数,只使用以下模式更新查询:
a -> [aàáaâäãåā]
e -> [eèéêëēėę]
i -> [iîïíīįì]
o -> [oôöòóøōõ]
u -> [uûüùúū]
y -> [yÿ]
s -> [sßśš]
l -> [lł]
z -> [zžźż]
c -> [cçćč]
n -> [nñń]
æ -> (?:æ|ae)
œ -> (?:œ|ce)
因此查询“hello”看起来像这样,作为正则表达式:
r"h[eèéêëēėę][lł][lł][oôöòóøōõ]"
将单词转换为正则表达式在任何语言中都应该相当简单。这不是已发布问题的解决方案 - “如何删除BigQuery中的重音?” - 但它是一个相关用例的解决方案,它可能会把人(像我这样!)带到这个页面。
你可以调用REPLACE()或REGEXP_REPLACE()。你可以在Remove accents/diacritics in a string in JavaScript找到一些正则表达式。
或者,您可以使用javascript UDF,但我希望它更慢。