在第二个和第三个连字符之间提取 TextString

Posted

技术标签:

【中文标题】在第二个和第三个连字符之间提取 TextString【英文标题】:Extract TextString between second and third hyphen 【发布时间】:2020-05-03 15:41:23 【问题描述】:

我正在尝试使用 RegEx 从我的一个列中的字符串中提取一些信息。

我需要定义第二列,等于第一列中第 2 次和第 3 次出现连字符之间的值。

经过多次谷歌搜索,我设法做到了这一点:

IFNULL(SAFE.REGEXP_EXTRACT(Final.CampaignName, r"(?:\w+\s+-\s+)2(\w+)\s+-"), "Other") AS CampaignCategory

Final.CampaignName 中的字符串的外观示例:

S - 橙子 - 酒吧 - 苹果

S - 苹果 - Foo Bar - 橙子 - 香蕉

S - 苹果 - 酒吧

如果第二个和第三个连字符之间有 1 个单词,我的正则表达式只会返回该值,但我需要返回整个文本(减去前导和尾随空格)。

谁能指导我做这件事的正确方向?

谢谢!

【问题讨论】:

请编辑以阐明每个示例要返回的内容。前两个很明显。对于第三个,第二个和第三个连字符之间没有文本(因为没有第三个连字符),那么要返回什么?一个空字符串?一个错误?如果您想返回Bar,您需要修改问题的措辞。不同的答案对此做出了不同的假设。 基于上下文 - 我强烈认为第三个示例的输出应该是 Bar。显然这是假设上下文被正确表示。 我很抱歉。我确实希望第三个示例也能返回Bar。谢谢你们两个的回答。 Cary 帮助我更好地理解 RegEx,而 Mikhail 为我的 BQ 示例提供了完美的答案 :) 【参考方案1】:

我快到了 - 所以,下面的内容尽可能接近您的原始想法(BigQuery 标准 SQL)

SELECT IFNULL(REGEXP_EXTRACT(final.CampaignName, r"(?: - .*?)2(.*?)(?: -|$)"), "Other") AS CampaignCategory

【讨论】:

【参考方案2】:

使用以下模式和捕获组来隔离您真正想要提取的内容:

SAFE.REGEXP_EXTRACT(Final.CampaignName, r"[^-]+-[^-]+-\s*([^-]+?)\s*-") AS CampaignCategory

Demo

【讨论】:

【参考方案3】:

您可以使用捕获组匹配第二个和第三个连字符之间的内容,并使用带有* 的重复模式将其余部分匹配为可选

\w+(?:\s+-\s+\w+)\s+-\s+(\w+(?: \w+)*)(?:\s+-\s+\w+)*

Regex demo

【讨论】:

【参考方案4】:

如果正则表达式引擎支持\K(松散地,忘记到目前为止匹配的所有内容),可以使用以下正则表达式来匹配第二个和第三个连字符之间的文本。

^(?:[^-]+-)2\K[^-]+(?=-)

请注意,此正则表达式不包含捕获组。

Demo

这与第三个示例中的 Bar 不匹配,因为只有两个连字符。要匹配 Bar,只需删除前瞻 (?=-)

正则表达式引擎执行以下操作。

^           match beginning of line
(?:[^-]+-)  match 1+ chars other than '-' followed by '-'
            in a non-capture group
2         execute non-capture group twice
\K          discard everything matched so far (reset the starting
            point of the reported match)
[^-]+       match 1+ chars other than '-'
(?=-)       match '-' in a positive lookahead

如果[^-] 不匹配换行符,请将其更改为[^-\r\n]

如果不支持\K,则需要捕获组(并且不需要前瞻):

^(?:[^-]+-)2([^-]+)-

【讨论】:

感谢您的解决方案和详尽的解释,Cary! REGEXP_EXTRACT 支持捕获组,因此不需要您的第一种方法。 @Tim,我认为是这样,但由于包括您自己在内的其他人提供了使用捕获组的解决方案,我想我会提出一些不同的建议,主要是出于教育原因。【参考方案5】:

如果可能,我总是更喜欢其他方式,而不是使用正则表达式。 因此,对于您的问题,我可以推荐该代码:

split(Final.CampaignName, ' - ')[safe_offset(2)]

您的示例数据示例:

select campaignName, split(campaignName, ' - ')[safe_offset(2)] as third_item
from unnest(['S - Oranges - Bar - Apples', 'S - Apples - Foo Bar - Oranges - Bananas', 'S - Apples - Bar']) as campaignName

输出如下所示:

【讨论】:

以上是关于在第二个和第三个连字符之间提取 TextString的主要内容,如果未能解决你的问题,请参考以下文章

SQL Regex 在第二个和第三个正斜杠之间选择字符串

XmlTextReader 忽略第二个和第三个 Profile 元素

如何使用选择器获取第二个和第三个元素?

第二个和第三个分布式 Kafka 连接器工作人员无法正常工作

单击预览后,如何在我的 React 应用程序上显示第二个和第三个按钮?

如何在不同的列中选择第一个、第二个和第三个值 - Ms Access