我正在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
。
答案 0 :(得分:1)
有问题的正则表达式可能看起来像这样:
(?:(?:|(\\|))f-150|keep|those):|(?:^|\\|)\\w-\\d{3}:\\w{2}
我添加了一些伪关键字来保留,但我相信您会明白的:
|
,然后将其放回$1
的替换中。根据documentation,您的查询应写为Java regex;同样,其效果应类似于code sample in Java。
答案 1 :(得分:1)
您可以匹配要删除的值,然后用空字符串替换:
f-150:|\|[^:]+:[^|]+$|[^|]+:[^|]+\|
f-150:|\\|[^:]+:[^|]+$|[^|]+:[^|]+\\|
说明
f-150:
字面上匹配|
或\|[^:]+:[^|]+$
匹配一个管道,而不是一个或多个冒号,然后匹配一个或多个管道,并断言行的结尾|
或[^|]+:[^|]+\|
不匹配一个或多个管道,冒号后不匹配一个或多个管道,然后匹配一个管道答案 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