正则表达式解析至少20个字符的文本,字符串中不带空格

时间:2019-02-14 13:06:18

标签: sql regex oracle

我需要在SQL查询中为Oracle DB解析手工输入的字符串字段中的代码,看起来像这样:

“我愿意/!* *使bb a8 001 / XYZ / 0002/65432178非常感谢您的朋友”

每行的单词数完全不同,只有相同的是单词之间的空格。 字符串中间的某个位置(但也可能是开头或结尾)是我需要解析的长度可变的CODE(总是至少20个字符)-代码始终没有空格,并且与其余部分分开文字按空格。 我只需要解析掉所有单词的代码。因此,在我看来,如何识别代码的唯一方法是将代码至少包含20个字符,且没有空格。 您可以推荐regex做这种事情吗? 非常感谢

所以我希望得到这样的字符串:“ 001 / XYZ / 0002/65432178”

2 个答案:

答案 0 :(得分:2)

您可以只查找一个序列的20多个实例,除空格外:

select regexp_substr(
  'i would ?! like / to make * bb a8 001/XYZ/0002/65432178 thank you very much friends',
  '[^ ]{20,}') as result
from dual;

RESULT               
---------------------
001/XYZ/0002/65432178

[^ ]是一种排除空格的模式; {20,}表示必须重复最少20次,最多没有重复。

如果您要排除任何空格-例如,在需要的部分之前或之后,有一个制表符而不是空格-您可以改用字符类:

regexp_substr(<your string>, '[^[:space:]]{20,}')

@MTO指出,这些将匹配值中的前20个字符的字符串,并且用户输入的文本可能包含您不希望看到的长非代码值,这是可行的。如果您可以匹配代码的预期模式,那就更好了。

答案 1 :(得分:2)

如果您的单词永远不会超过20个字符,那么您可以天真地使用:

SELECT REGEXP_SUBSTR( value, '\S{20,}' ) AS code,
       value
FROM   data d;

但是,如果您的单词长度超过20个字符,例如:

CREATE TABLE data ( value ) AS
SELECT 'long words like floxinoxinihilipilification and antidisestablishmentarianism with your code 001/XYZ/0002/65432178' FROM DUAL UNION ALL
SELECT 'i would ?! like / to make * bb a8 001/XYZ/0002/65432178 thank you very much friends' FROM DUAL;

然后上述代码输出:

CODE                        | VALUE                                                                                                            
:-------------------------- | :----------------------------------------------------------------------------------------------------------------
floxinoxinihilipilification | long words like floxinoxinihilipilification and antidisestablishmentarianism with your code 001/XYZ/0002/65432178
001/XYZ/0002/65432178       | i would ?! like / to make * bb a8 001/XYZ/0002/65432178 thank you very much friends                              

相反,您可以尝试执行类似的操作,例如返回包含20个以上字符的单词,这些单词也包含最多/个字符:

SELECT ( SELECT MAX( REGEXP_SUBSTR( d.value, '\S{20,}', 1, LEVEL ) ) KEEP ( DENSE_RANK LAST ORDER BY REGEXP_COUNT( REGEXP_SUBSTR( d.value, '\S{20,}', 1, LEVEL ), '/' ) )
         FROM   DUAL
         CONNECT BY LEVEL <= REGEXP_COUNT( d.value, '\S{20}' )
       ) AS code,
       value
FROM   data d;

哪个输出:

CODE                  | VALUE                                                                                                            
:-------------------- | :----------------------------------------------------------------------------------------------------------------
001/XYZ/0002/65432178 | long words like floxinoxinihilipilification and antidisestablishmentarianism with your code 001/XYZ/0002/65432178
001/XYZ/0002/65432178 | i would ?! like / to make * bb a8 001/XYZ/0002/65432178 thank you very much friends                              

db <>提琴here