如何使用正则表达式在逗号之间选择文本?

时间:2018-08-16 04:31:15

标签: regex google-bigquery re2

我正在Google Cloud Platform上使用BigQuery从GDELT中提取数据。这使用了SQL语法和正则表达式。

我有一列数据(称为V2Tone),其中每个单元格如下所示:

1.55763239875389,2.80373831775701,1.24610591900312,4.04984423676012,26.4797507788162,2.49221183800623,299

要使用正则表达式仅选择第一个数字(即,第一个逗号之前的数字),我们使用以下方法:

regexp_replace(V2Tone, r',.*', '')

我们如何仅选择第二个数字(即,第一个和第二个逗号之间的数字)

第三个数字(即第二个和第三个逗号之间的数字)如何?

我知道这里使用了re2语法(https://github.com/google/re2/wiki/Syntax),但是我对如何将所有内容组合在一起的理解有限。

如果不清楚,请通知我。感谢您在我学习使用正则表达式时的帮助。

3 个答案:

答案 0 :(得分:3)

下面的示例适用于使用超级简单的SPLIT方法的BigQuery Standard SQL

#standardSQL
SELECT 
  SPLIT(V2Tone)[SAFE_OFFSET(0)] first_number,
  SPLIT(V2Tone)[SAFE_OFFSET(1)] second_number,
  SPLIT(V2Tone)[SAFE_OFFSET(2)] third_number
FROM `project.dataset.table`  

如果出于某种原因您需要/想要在此处使用regexp-在下面使用

#standardSQL
SELECT 
  REGEXP_EXTRACT(V2Tone, r'^(.*?),') first_number,
  REGEXP_EXTRACT(V2Tone, r'^(?:(?:.*?),)(.*?),') second_number,
  REGEXP_EXTRACT(V2Tone, r'^(?:(?:.*?),){2}(.*?),') third_number,
  REGEXP_EXTRACT(V2Tone, r'^(?:(?:.*?),){4}(.*?),') fifth_number
FROM `project.dataset.table`  

请注意使用REGEXP_EXTRACT代替REGEXP_REPLACE

您可以使用以下问题中的虚拟字符串播放,测试以上选项

#standardSQL
WITH `project.dataset.table` AS (
  SELECT '1.55763239875389,2.80373831775701,1.24610591900312,4.04984423676012,26.4797507788162,2.49221183800623,299' V2Tone
)
SELECT 
  SPLIT(V2Tone)[SAFE_OFFSET(0)] first_number,
  SPLIT(V2Tone)[SAFE_OFFSET(1)] second_number,
  SPLIT(V2Tone)[SAFE_OFFSET(2)] third_number,
  REGEXP_EXTRACT(V2Tone, r'^(.*?),') first_number_re,
  REGEXP_EXTRACT(V2Tone, r'^(?:(?:.*?),)(.*?),') second_number_re,
  REGEXP_EXTRACT(V2Tone, r'^(?:(?:.*?),){2}(.*?),') third_number_re,
  REGEXP_EXTRACT(V2Tone, r'^(?:(?:.*?),){4}(.*?),') fifth_number_re
FROM `project.dataset.table`  

输出:

first_number        second_number       third_number        first_number_re    second_number_re    third_number_re     fifth_number_re     
1.55763239875389    2.80373831775701    1.24610591900312    1.55763239875389    2.80373831775701    1.24610591900312    26.4797507788162     

答案 1 :(得分:2)

我不知道可以使用一个正则表达式替换来隔离CSV字符串中的单个数字,因为一般来说,我们需要删除比赛双方的内容。但是,我们可以将两个对regex_replace的调用链接在一起。例如,如果您要定位CSV字符串中的第三数字,我们可以尝试以下操作:

regexp_replace(regexp_replace(V2Tone, r'^(?:(?:\d+(?:\.\d+)?),){2}', ''),
    r',.*', ''))

我用来剥离前n个数字的模式是这样的:

^(?:(?:\d+(?:\.\d+)?),){n}

这只是从字符串的开头删除一个数字,然后删除n次逗号。

Demo

答案 2 :(得分:2)

这是一个使用单个正则表达式替换的解决方案:

^([^,]+(?:,|$)){2}([^,]+(?:,|$))*|^.*$

Demo

\n已添加到演示中的否定字符类中,以避免在m | multiline模式下匹配跨行。

用法:

regexp_replace(V2Tone, r'^([^,]+(?:,|$)){2}([^,]+(?:,|$))*|^.*$', '$1')

说明:

  • ([^,]+(?:,|$){n}将所有内容捕获到下一个逗号或字符串结尾n
  • ([^,]+(?:,|$))*捕获其余0次或更多次
  • 如果我们无法匹配^.*$次,
  • n会捕获一切

最后,我们可以使用n重新插入第$1个匹配项。