大写一个RegEx替换Google Bigquery中的Capture组

时间:2015-01-27 01:48:55

标签: sql regex google-bigquery regexp-replace

我正在尝试做一些非常简单的事情,在Big Query中变得非常复杂。我想把像人名这样的东西转换成正确的情况(每个单词大写的第一个字母)。

这是我目前正在处理的查询,它几乎可以运行!

SELECT 
REGEXP_REPLACE(
    CONCAT(
        UPPER(LEFT('tESt ing', 1)), 
        LOWER(SUBSTR('tESt ing', 2))
    ),
    ' ([a-z])', 
    UPPER(' \\1')
);

#outputs: Test ing
#desired output: Test Ing

由于某种原因,UPPER不会处理捕获的组。 如果我把其他文本放入其中它全部变为大写但cap组变量保持小写。

任何帮助都非常感谢。这似乎并不像预期的那样有效(可能是操作顺序......)。无论如何,提前谢谢。

埃里克

4 个答案:

答案 0 :(得分:2)

所以我首先尝试了一种费力的但我认为直截了当的方法:

SELECT
CONCAT(
    UPPER(LEFT('tESt ing', 1)), 
    LOWER(REGEXP_EXTRACT(SUBSTR('tESt ing', 2), r'(\w* )')),
    UPPER(REGEXP_EXTRACT(SUBSTR('tESt ing', 2), r' (\w)')),
    LOWER(REGEXP_EXTRACT(SUBSTR('tESt ing', 2), r' \w(.*)'))
);

似乎有效,并根据需要返回Test Ing

然后我尝试了一些简化(我希望)减少工作量:

SELECT
CONCAT(
    UPPER(LEFT('tESt ing', 1)), 
    LOWER(REGEXP_EXTRACT('tESt ing', r'.(\w* )')),
    UPPER(REGEXP_EXTRACT('tESt ing', r' (\w)')),
    LOWER(REGEXP_EXTRACT('tESt ing', r' \w(.*)'))
);

这也似乎有效(相同的输出)。但是它只删除SUBSTR次调用 - 而不是我担心的正则表达式操作可能会更昂贵。

仍然认为这可能值得分享。

答案 1 :(得分:1)

我不是百分百肯定,但似乎正则表达式在其中的字符串操作之后得到了评估。

作为替代方案,请尝试SPLIT():

SELECT GROUP_CONCAT(capw, ' ') capitalized_name, FIRST(x) x, id
FROM (
  SELECT UPPER(LEFT(w, 1)) + LOWER(SUBSTR(w, 2)) capw, x, POSITION(w) pos, id
  FROM (
    SELECT SPLIT(x, ' ') w, id
    FROM (SELECT 'name lastname' x, 1 id), (SELECT 'name other name' x, 2 id), (SELECT 'a b c' x, 3 id), (SELECT 'name lastname' x, 4 id) 
  )
  ORDER BY pos
)
GROUP BY id

enter image description here

答案 2 :(得分:0)

可以更好地扩展的替代方法 - 您可以在1500万个记录名称数据集上进行测试吗?

SELECT capitalized_name, x, id FROM (
SELECT GROUP_CONCAT(capw, ' ')  OVER(PARTITION BY id ORDER BY pos) capitalized_name, x, id, ROW_NUMBER() OVER(PARTITION BY id ORDER BY pos DESC) rn
FROM (
  SELECT UPPER(LEFT(w, 1)) + LOWER(SUBSTR(w, 2)) capw, x, POSITION(w) pos, id
  FROM (
    SELECT SPLIT(rdf_schema_label, ' ') w, rdf_schema_label x, URI id
    FROM [dbpedia2014temp.Person]
  )
  ORDER BY pos
)
) WHERE rn=1

答案 3 :(得分:-1)

REGEX_REPLACE不是MySQL函数,必须实现。 这是一个名为ucwords的函数:

    DELIMITER ||

CREATE FUNCTION `ucwords`( str VARCHAR(128) ) RETURNS varchar(128) CHARSET latin1
BEGIN
DECLARE c CHAR(1);
DECLARE s VARCHAR(128);
DECLARE i INT DEFAULT 1;
DECLARE bool INT DEFAULT 1;
DECLARE punct CHAR(17) DEFAULT ' ()[]{},.-_!@;:?/';
SET s = LCASE( str );
WHILE i < LENGTH( str ) DO
BEGIN
SET c = SUBSTRING( s, i, 1 );
IF LOCATE( c, punct ) > 0 THEN
SET bool = 1;
ELSEIF bool=1 THEN
BEGIN
IF c >= 'a' AND c <= 'z' THEN
BEGIN
SET s = CONCAT(LEFT(s,i-1),UCASE(c),SUBSTRING(s,i+1));
SET bool = 0;
END;
ELSEIF c >= '0' AND c <= '9' THEN
SET bool = 0;
END IF;
END;
END IF;
SET i = i+1;
END;
END WHILE;
RETURN s;
END ||

DELIMITER ;

然后你可以使用:来自dual =&gt;的SELECT ucwords('tEst iNg')测试Ing