正则表达式删除不匹配特定前缀的元素

时间:2018-06-27 22:59:29

标签: sql regex hive impala

我正在Impala或Hive中进行此操作。基本上说我有一个像这样的字符串

f-150:aa|f-150:cc|g-210:dd

每个元素由管道|分隔。每个都有前缀f-150或其他前缀。我希望能够删除前缀并仅保留与特定前缀匹配的元素。例如,如果前缀为f-150,则我希望regex_replace之后的最后一个字符串为

aa|cc

dd被删除,因为g-210是不同的前缀并且不匹配,因此整个元素都被删除。

有什么主意如何在一个SQL中使用字符串表达式来做到这一点?

谢谢

更新1

我在Impala中尝试过:

select regexp_extract('f-150:aa|f-150:cc|g-210:dd','(?:(?:|(\\|))f-150|keep|those):|(?:^|\\|)\\w-\\d{3}:\\w{2}',0);

但是得到了以下输出:

f-150:aa

Hive中,我得到了NULL

3 个答案:

答案 0 :(得分:1)

有问题的正则表达式可能看起来像这样:

(?:(?:|(\\|))f-150|keep|those):|(?:^|\\|)\\w-\\d{3}:\\w{2}

我添加了一些伪关键字来保留,但我相信您会明白的:

  • 应该匹配哪些元素,但只匹配应该保留的元素的前缀。
  • 要保持分隔符完整,请在组1中元素的开头匹配|,然后将其放回$1的替换中。

Demo

根据documentation,您的查询应写为Java regex;同样,其效果应类似于code sample in Java

答案 1 :(得分:1)

您可以匹配要删除的值,然后用空字符串替换:

f-150:|\|[^:]+:[^|]+$|[^|]+:[^|]+\|

f-150:|\\|[^:]+:[^|]+$|[^|]+:[^|]+\\|

说明

  • f-150:字面上匹配
  • |
  • \|[^:]+:[^|]+$匹配一个管道,而不是一个或多个冒号,然后匹配一个或多个管道,并断言行的结尾
  • |
  • [^|]+:[^|]+\|不匹配一个或多个管道,冒号后不匹配一个或多个管道,然后匹配一个管道

Test with multiple lines and combinations

答案 2 :(得分:0)

您可能必须遍历字符串直到最后才能获得所有匹配的子字符串。大多数SQL不支持向前看语法,因此上述regexp可能不适用于SQL语法。为了您的目的,您可以执行类似创建表的操作,以模仿Oracle的级别语法并与包含字符串的表联接。

div.sidebar-wrapper

输出:

With loop_tab as (
Select 1 loop union all
Select 2 union all
select 3 union all
select 4 union all
select 5),
string_tab as(Select 'f-150:aa|ade|f-150:ce|akg|f-150:bb|'::varchar(40) as str)
Select regexp_substr(str,'(f\\-150\\:\\w+\\|)',1,loop)
from string_tab
join loop_tab on 1=1