首先让我提一下这是一个讨论得很好的问题,我已经经历了几个线程,包括这两个 - 最接近的匹配Regex to match a string not followed by some string和A regex to match a substring that isn't followed by a certain other substring,但它们并没有解决我的问题。
我有几种不同格式的体积和数量的字符串 - 如下所述,例如: 6 X 200ml意味着6包200毫升。我想在这个例子中只提取像6这样的数量
实施例
这是我迄今为止尝试过的,没有任何成功
(X\s*\d+|\d+\s*X)(?!\s*ml)
它匹配情况#3和4,它们不应匹配。我也很好,用乘法符号提取数量为6,例如6 X而不是6。我可以替换它。
答案 0 :(得分:0)
您没有提到您在问题中使用的数据库。
SQL标准不包含正则表达式,因此每个数据库都有自己的regexp引擎实现,每个都是不同的,不支持正则表达式的许多功能,如lookarounds。如果不知道您正在使用的确切数据库,很难帮助您。
下面是两个简单的例子,说明如何使用
在Oracle和PostgreSQL数据库中解决这个问题
但这将不适用于除Oracle / PostgreSQL之外的其他数据库
对Oracle的查询:
在线演示:http://sqlfiddle.com/#!4/599c41/5
select t.*,
regexp_substr( regexp_replace( "text", '\d+\s*ml', '///' ), '\d+' ) as x
from table1 t;
| text | X |
|-------------------|--------|
| blah 6 X 200ml | 6 |
| blah 200 mlX 6 | 6 |
| blah x 5000 ml | (null) |
| blah x 500000ml | (null) |
| blah 5mlX10 | 10 |
| blah 500 mlX 10 | 10 |
如果要将NULL替换为0或1,可以这样使用CASE EXPRESSION:
select t.*,
CASE WHEN regexp_substr( regexp_replace( "text", '\d+\s*ml', '///' ), '\d+' )
IS NULL THEN '1' /* or 0 */
ELSE regexp_substr( regexp_replace( "text", '\d+\s*ml', '///' ), '\d+' )
END as x
from table1 t;
| text | X |
|-------------------|----|
| blah 6 X 200ml | 6 |
| blah 200 mlX 6 | 6 |
| blah x 5000 ml | 1 |
| blah x 500000ml | 1 |
| blah 5mlX10 | 10 |
| blah 500 mlX 10 | 10 |
对PostgreSQL的查询:
select t.*,
substring( regexp_replace( "text", '\d+\s*ml', '///') from '\d+' ) as x
from table1 t;
| text | x |
|-------------------|--------|
| blah 6 X 200ml | 6 |
| blah 200 mlX 6 | 6 |
| blah x 5000 ml | (null) |
| blah x 500000ml | (null) |
| blah 5mlX10 | 10 |
| blah 500 mlX 10 | 10 |