【问题标题】:Does regexp_extract work for multiple patterns?-Spark sqlregexp_extract 是否适用于多种模式?-Spark sql
【发布时间】:2021-05-28 13:02:32
【问题描述】:

模式1:由|分隔

Input : a|b|c|d     
Output: a|b|c|d 

用一个竖线分隔时选择所有内容

模式 2:由 | 分隔和 ||
示例1:

Input :a|b||c||d       
Output:a|b||c   

选择最后一个双管道之前的所有内容

示例2:

Input :a|b||c|d     
Output:a|b   

模式 3:字符串的开头可以有多个管道(奇数或偶数)并进一步由 | 分隔和||

Input :|||a|b||c||d     
Output:|||a|b||c 

选择最后一个双管道之前的所有内容,字符串的开头可能有奇数或偶数管道,必须选择它们。

以下涵盖除场景1之外的所有场景,我的要求是涵盖所有场景regexp_extract spark.sql("select regexp_extract('name|place|thing|ink', '(.*)(?=\\\\|\\\\|)') as demo").show(false)

如果不能在一个 regexp_extract 中完成。您能否建议其他选项。

请指教。

【问题讨论】:

  • 格式化您的问题,以便代码和数据是等宽的。在每行代码/数据上添加四个或更多空格。
  • 欢迎来到 SO Priya。你的问题很有趣。请看下面我的回答。无论如何,请按照指南正确格式化问题中的代码和数据。如果您发现它满足您的要求,也请考虑accept an answer。如果需要任何澄清,请告诉我。

标签: regex extract


【解决方案1】:

使用以下正则表达式:

^(\|*(?:(?!\|\|(?!.*\|\|)).)*)

查看RegEx Demo 显示所有匹配项

这是一个相当复杂的要求,需要在 Tempering 模式中使用 Tempered Greedy Token 和 Negative Lookahead。让我解释一下下面的逻辑:

逻辑

  • ^ 只匹配字符串的开头
  • (...)^ 之后包含整个模式以使其成为捕获组
  • \|* 要求 Pattern 3 匹配开头的多个|,尽可能多(因此使用贪婪*
  • (?:(?!...).)*这是Tempered Greedy Token的主要构造(骨架),我将在下面解释其详细信息:
  • \|\|(?!.*\|\|) 这是 Tempered Greedy Token 的主体(核心)。 ( 之前的第一部分是确保字符匹配但不包括模式|| 第二部分(?!.*\|\|) 是确保第一部分中的|| 模式后面没有任何其他双管道@ 987654337@ 之后的某个地方,根据要求。

事实上,我认为这个问题很有趣,需要 RegEx 的复杂功能来支持它。这也是迄今为止我看到的第一个需要在 Tempered Greedy Token 构造中进行 Negative Lookahead 的示例。

【讨论】:

  • 谢谢!上述解决方案在 hive 中有效,但 Spark sql 抛出错误“在索引 3 处悬空元字符 *。由于 * 是一个量词,我认为我们不应该逃避它。我只是尝试用\* 但仍然出现悬空元字符错误。
  • 对不起,我对 Spark SQL 不熟悉。无论如何,看到你尝试过的正则表达式,即(.*)(?=\\\\|\\\\|) 也有*,所以我猜这个问题并不在* 量词上。我的疯狂猜测是反斜杠 \ 用于转义符号。看到您使用 4 \ 来转义 | 符号,而我只使用了一个 \,它在可能被引用时在其他 RegEx 环境中被接受。您可以尝试在上述正则表达式中添加更多 \ 并重试吗?
  • 嗨@Priya,当您尝试自定义正则表达式以使其在 Spark sql 下可用时,我进一步微调了正则表达式以对其进行概括,以涵盖您的问题中未提及的更多示例案例:例如||||a|b||c|a||f 末尾的双斜线段不一定放在一起(中间可以有单斜线段)。请将此增强的正则表达式用于您的工作。
  • @SeaBean-for Spark Sql 我在下面的帖子stackoverflow.com/questions/66388303/… 中使用了这种方法。尽管如此,感谢您的帮助。我是正则表达式的新手,如果您能分享学习它的建议,那就太好了。
  • @Priya 太好了,您从了解 Spark Sql 的人那里找到了解决方案。回答你的人也是正则表达式的大师。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-20
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多