【问题标题】:keep string based on substring基于子字符串保留字符串
【发布时间】:2020-07-09 14:45:54
【问题描述】:

我需要保留那些包含子字符串一部分的单词。例如:

select regexp_substr('libstdc++-devel-4.8.5-39.0.3.el7.x86_64, python-kitchen-1.1.1-5.el7.noarch, nfs-utils-1.3.0-0.65.0.1.el7.x86_64, git-1.8.3.1-20.el7.x86_64', 
       '(.+?)(devel|git|nfs).+?\,') st from dual;

这个查询返回libstdc++-devel-4.8.5-39.0.3.el7.x86_64,但我还需要git-1.8.3.1-20.el7.x86_64 > 和 nfs-utils-1.3.0-0.65.0.1.el7.x86_64 基于模式。请注意,我每行有几十个单词(不仅仅是这 4 个),所以我需要调整模式,扩展结果(比如添加 grub、perl 等)。 谢谢。

【问题讨论】:

  • 看起来你的解决方案是here

标签: sql regex oracle


【解决方案1】:

您的正则表达式存在一些问题;它将匹配(例如)python-kitchen-1.1.1-5.el7.noarch, nfs-utils-1.3.0-0.65.0.1.el7.x86_64,,因为它允许在匹配之前使用空格和逗号来匹配develgitnfs(在(.+?) 中)之一。此外,它不会匹配git-1.8.3.1-20.el7.x86_64,因为它需要在匹配结束时使用逗号。您可以通过将(.+?) 替换为[^ ]* 并将\, 替换为(,|$) 来解决这些问题。然后,您可以使用源自this question 的解决方案(尽管以我的首选形式,在CONNECT BY 中检查NOT NULL)来获得所有结果:

SELECT REGEXP_SUBSTR(str, '[^ ]*(devel|git|nfs).+?(,|$)', 1, level) AS lib
FROM (
  SELECT 'libstdc++-devel-4.8.5-39.0.3.el7.x86_64, python-kitchen-1.1.1-5.el7.noarch, nfs-utils-1.3.0-0.65.0.1.el7.x86_64, git-1.8.3.1-20.el7.x86_64' as str
  FROM dual
)
CONNECT BY REGEXP_SUBSTR(str, '[^ ]*(devel|git|nfs).+?(,|$)', 1, level) IS NOT NULL

输出:

LIB
libstdc++-devel-4.8.5-39.0.3.el7.x86_64,
nfs-utils-1.3.0-0.65.0.1.el7.x86_64,
git-1.8.3.1-20.el7.x86_64

注意这会在某些名称的末尾留下逗号,如果你想去掉它们,只需使用RTRIM

SELECT RTRIM(REGEXP_SUBSTR(str, '[^ ]*(devel|git|nfs).+?(,|$)', 1, level), ',') AS lib
FROM (
  SELECT 'libstdc++-devel-4.8.5-39.0.3.el7.x86_64, python-kitchen-1.1.1-5.el7.noarch, nfs-utils-1.3.0-0.65.0.1.el7.x86_64, git-1.8.3.1-20.el7.x86_64' as str
  FROM dual
)
CONNECT BY REGEXP_SUBSTR(str, '[^ ]*(devel|git|nfs).+?(,|$)', 1, level) IS NOT NULL

输出:

LIB
libstdc++-devel-4.8.5-39.0.3.el7.x86_64
nfs-utils-1.3.0-0.65.0.1.el7.x86_64
git-1.8.3.1-20.el7.x86_64

如果要在一行中获取所有值,可以将第一个查询用作CTE,然后在结果上使用LISTAGG

WITH CTE AS (
  SELECT level AS l, REGEXP_SUBSTR(str, '[^ ]*(devel|git|nfs).+?(,|$)', 1, level) AS lib
  FROM (
    SELECT 'libstdc++-devel-4.8.5-39.0.3.el7.x86_64, python-kitchen-1.1.1-5.el7.noarch, nfs-utils-1.3.0-0.65.0.1.el7.x86_64, git-1.8.3.1-20.el7.x86_64' as str
    FROM dual
  )
  CONNECT BY REGEXP_SUBSTR(str, '[^ ]*(devel|git|nfs).+?(,|$)', 1, level) IS NOT NULL
)
SELECT LISTAGG(lib) WITHIN GROUP (ORDER BY l) AS lib
FROM CTE

输出:

LIB
libstdc++-devel-4.8.5-39.0.3.el7.x86_64,nfs-utils-1.3.0-0.65.0.1.el7.x86_64,git-1.8.3.1-20.el7.x86_64

Demo on dbfiddle

【讨论】:

  • 我点击你的答案是有用的,但正如我所提到的,我需要将结果保持在同一行,而不是分开。我实际上尝试使用(没有成功):select regexp_replace('libstdc++-devel-4.8.5-39.0.3.el7.x86_64, python-kitchen-1.1.1-5.el7.noarch, nfs-utils-1.3. 0-0.65.0.1.el7.x86_64, git-1.8.3.1-20.el7.x86_64', '[^ ]*(devel|git|nfs).+?(,|$)', '\1, ' ) st 来自对偶;使用 TRIM 很简单,我需要这个结果:libstdc++-devel-4.8.5-39.0.3.el7.x86_64, git-1.8.3.1-20.el7.x86_64, nfs-utils-1.3.0-0.65。 0.1.el7.x86_64.谢谢
  • @misurex 道歉 - 我错过了问题的那一部分。在一行上获得结果的最简单方法是LISTAGG 第一个查询的结果,因为尝试替换不匹配的内容非常棘手,尤其是在没有前瞻的情况下。查看我的编辑。
  • 谢谢尼克,我可以使用这个解决方法,谢谢。
  • @misurex 不用担心 - 我很高兴能帮上忙。
猜你喜欢
  • 2017-02-15
  • 1970-01-01
  • 2021-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 2018-12-08
  • 1970-01-01
相关资源
最近更新 更多