【问题标题】:Get second match from regexp_matches results从 regexp_matches 结果中获取第二个匹配项
【发布时间】:2018-09-05 06:52:10
【问题描述】:

我有一个name 列,如下所示:

'1234567 - 7654321 - some - more - text'

我需要得到一个字符串"7654321"。我坚持以下几点:

SELECT regexp_matches('1234567 - 7654321 - some - more - text', '\d+', 'g');

regexp_matches
----------------
{1234567}
{7654321}

(2 rows)

我怎么做我想要的?也许有比regexp_matches 更好的选择 - 很乐意考虑。谢谢!

【问题讨论】:

  • 试试SELECT regexp_matches('1234567 - 7654321 - some - more - text', '-\s*(\d+) -');
  • @WiktorStribiżew 好一个!但返回一个数组
  • SELECT substring('1234567 - 7654321 - some - more - text', '- (\d+) -'); 呢?
  • @WiktorStribiżew 这在控制台中有效,但是当我尝试将其用于我需要的内容(设置新列的值)时,它无法设置为 null

标签: sql regex postgresql


【解决方案1】:

你可以使用REGEXP_REPLACE:

SELECT REGEXP_REPLACE('1234567 - 7654321 - some - more - text', '^\d+[^\d]+(\d+).*$', '\1');

输出

7654321

此正则表达式查找以一些数字开头的字符串 (^\d+),后跟一些非数字字符 ([^\d]+),然后是另一组数字 ((\d+)),后跟一些字符,直到字符串的结尾 (.*$)。第二组数字字符周围的() 使它成为一个捕获组,然后我们可以在替换字符串中使用\1 引用它。由于REGEXP_REPLACE 仅替换与正则表达式匹配的字符串部分,因此必须有一个与整个 字符串匹配的正则表达式才能将其替换为所需的数据。

更新

如果在第一组数字之前有潜在的字符,您应该将正则表达式更改为

^[^\d]*\d+[^\d]+(\d+).*$

更新 2

如果开头可能只有一组数字,我们必须将匹配第一部分设为可选。我们可以使用非捕获组来做到这一点:

^[^\d]*(?:\d+[^\d]+)?(\d+).*$

这使得第一组数字的匹配是可选的,因此如果它不存在(即只有一组数字),正则表达式仍然会匹配。通过使用非捕获组(将?:添加到组的开头,我们不需要从\1更改替换字符串。更新SQLFiddle

【讨论】:

  • 我喜欢这样,你能解释一下正则表达式和\1 标志的含义吗?正则表达式的总菜鸟,谢谢!
  • @AndreyDeineko 我已经为答案添加了解释。
  • 基本上我想从一个字符串中得到第二个匹配\d+,也许我们可以有更简单的表达式?
  • 嘿,我在update 查询中使用它,就像UPDATE tbl SET column = REGEXP_REPLACE(name, '^\d+[^\d]+(\d+).*$', '\1') WHERE ... - 错了吗?它设置name 列的全部内容,而不是所需的子字符串
  • 如果它为您提供了全部内容,则表示正则表达式不匹配。失败的name 的值是多少?
【解决方案2】:

regexp_matches() 返回一个表,因此您可以在 from 子句中将其与 with ordinality 选项一起使用:

SELECT t.value
from regexp_matches('1234567 - 7654321 - some - more - text', '\d+', 'g') with ordinality as t(value,idx)
where t.idx = 2;

请注意,value 仍然是一个数组,要获取您可以使用的实际数组元素:

SELECT t.value[1]
from regexp_matches('1234567 - 7654321 - some - more - text', '\d+', 'g') with ordinality as t(value,idx)
where t.idx = 2;

【讨论】:

  • 非常感谢您的帮助!我选择了正则表达式
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 2022-07-20
  • 1970-01-01
相关资源
最近更新 更多