如何使用正则表达式来 select 逗号之间的文本?

How can I use regular expressions to select text between commas?

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

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

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

到select只有第一个数字(即第一个逗号前的数字)使用正则表达式,我们使用这个:

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

如何才能select只有第二个数字(即第一个和第二个逗号之间的数字)?

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

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

如有不明之处,请告诉我。感谢您帮助我学习使用正则表达式。

我不知道可以使用单个正则表达式替换来隔离 CSV 字符串中的单个数字,因为通常我们需要删除匹配两边的内容。但是,我们可以将对 regex_replace 的两个调用链接在一起。例如,如果您想定位 CSV 字符串中的 third 数字,我们可以尝试这样做:

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

我用来去除前 n 个数字的模式是这样的:

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

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

Demo

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

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

Demo

\n在demo中的取反符class后面添加,避免m|多行模式下跨行匹配

用法:

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

解释:

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

最后,我们可以使用 </code>.</p> 重新插入第 <code>n 个匹配项

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

#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`  

如果出于某种原因您 need/want 在这里使用正则表达式 - 请在下面使用

#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