Regex 如何在PostgreSQL中提取后跟特定字符串的数字?

Regex 如何在PostgreSQL中提取后跟特定字符串的数字?,regex,postgresql,postgresql-9.5,Regex,Postgresql,Postgresql 9.5,我有下表: CREATE TABLE test_regex ( drug TEXT ); INSERT INTO test_regex VALUES ('DRUGA 200 MG'), ('DRUGB 150 MCG'), ('DRUGC 1.5 GM BOX'), ('DRUGD 27.2 MG/5 ML VIAL') ; 我想摘录以下内容: 200 MG 150 MCG 1.5 GM 27.2 MG 到目前为止,我所尝试的: SELECT

我有下表:

CREATE TABLE test_regex (
    drug TEXT
);

INSERT INTO test_regex
VALUES
    ('DRUGA 200 MG'),
    ('DRUGB 150 MCG'),
    ('DRUGC 1.5 GM BOX'),
    ('DRUGD 27.2 MG/5 ML VIAL')
;
我想摘录以下内容:

200 MG
150 MCG
1.5 GM
27.2 MG
到目前为止,我所尝试的:

SELECT
    substring(drug, '[0-9]*\.?[0-9]* MG|GM|MCG')
FROM
    test_regex
;
其结果是:

 200 MG
 MCG
 GM
 27.2 MG
我也试过:

SELECT
    substring(drug, '[0-9]*\.?[0-9]* (MG|GM|MCG)')
FROM
    test_regex
;
因此:

 MG
 MCG
 GM
 MG

我认为问题在于后面的
(MG | GM | MCG)
组是如何处理的,但我在PostgreSQL文档中找不到我想要的内容。我希望得到第一个数字部分,然后是一个空格,然后是MG、GM或MCG。我认为它被分组为带有MG的数字表达式,然后是GM或MCG。

主要思想是,您需要将在字符串中的同一位置匹配的备选方案分组。此外,我建议使用单词边界将字符串作为整个单词进行匹配

另外,请注意,如果存在以下情况,则只返回捕获组捕获的匹配部分:

如果模式包含任何括号,则返回与第一个带括号的子表达式(左括号位于第一位的子表达式)匹配的文本部分

因此,您可以使用的分组构造是,
(?:…|…)

你可以用

substring(drug, '\m[0-9]*\.?[0-9]+\s*(?:MG|GM|MCG)\M')

图案细节

  • \m
    -单词的开头
  • [0-9]*
    -零位或更多位
  • \?
    -可选的
  • [0-9]+
    -1+位
  • \s*
    -0+空格
  • (?:MG | GM | MCG)
    -要么
    MG
    ,要么
    GM
    MCG
    (您可以将其写成
    (?:MC?G | GM)
    ,以提高效率)
  • \M
    -词尾

A应该可以做到这一点,尽管我不确定如何在Postgres中编写这些内容。与捕获组(带有括号的默认值)不同,它不会更改匹配语义。话虽如此,也许还有一种方法可以让您的捕获组工作,通过某种方式选择您想要的匹配组作为结果。(通常情况下,匹配组0是完全匹配,而匹配组1是第一个捕获组,即您看到的作为结果的组。)
?:
使该组成为非捕获组成功。你能解释一下单词开头和结尾的原因吗?再次感谢@Gregoyarenius
\m..\m
=
\y..\y
(在其他正则表达式中,
\b..\b
)用于匹配整个单词(它与
5mgg
@Wiktor Stribiżew中的
5MG
不匹配再次感谢您在子字符串函数中添加了文档的最后一位,以及它如何处理捕获组。这让我清楚了发生了什么。