在PL / SQL中如何在不截断单词的情况下拆分字符串?

时间:2019-05-17 11:14:20

标签: sql regex plsql

我有一个表Data,表Note包含一个长字符串。我想每30个字符分割一次每个字符串的内容,而不会截断单词。这意味着如果拆分将截断一个单词,则应在该单词之前拆分并从下一个重新开始拆分过程:

使用每个7个字符分割的示例

数据

--------------------------
| Id | Note              |
--------------------------
|  1 |I am dumb using SQL|
--------------------------
... more rows ...
--------------------------

结果

----------------
| Id | Note    |    
----------------
|  1 |I am     |
----------------
|  2 |dumb     |
----------------
|  3 |using    |
----------------
|  4 |SQL      |
----------------

请注意第一次拆分是如何发生的:前7个字符为I am du,因为第七个字符的拆分将截断单词dumb,该拆分之前被应用,结果为{{1 }}。

一些代码可以复制示例以及我尝试解决的问题:

I am

2 个答案:

答案 0 :(得分:2)

假设您不想删节较长的单词:

([^ ]{1}.{1,6}(?= ))|([^\n ]{1,})

正则表达式主要组的说明:

([^ ]{1}.{1,6}(?= ))-一个非空格,后跟最多6个字符,后跟一个空格(正向超前)。

([^\n ]{1,})-一个或多个非空格,非换行符。正则表达式的这一部分负责覆盖比7(或30)个字符更长的单词,并覆盖字符串中的最后一个单词。

您应将6替换为n-1,其中n是不被截断而可以容纳的字符数(在您的情况下为7或30)。我已经使用Notepad ++开发了此正则表达式,但不能保证它会在您的环境中正常工作。

答案 1 :(得分:1)

我假设您正在尝试获取处理多个行的示例?

with tbl_source(id, txt) as (
  select 1, 'I am dumb using SQL'     from dual union all
  select 2, 'This is a test of row 2' from dual
),
tbl_main(id, rownbr, txt, txt_length) as (
select id, level as rownbr, trim(regexp_substr(txt,'.{1,7}( |$)',1,level)) as txt,
       length(trim(regexp_substr(txt,'.{1,7}( |$)',1,level))) txt_length
       from tbl_source
       connect by level <= ceil(length(txt)/7)+1
       and prior txt = txt
       and prior sys_guid() is not null 
)
select id, rownbr, txt, txt_length
from tbl_main
where txt is not null
order by id, rownbr;

输出:

        ID     ROWNBR TXT                     TXT_LENGTH
---------- ---------- ----------------------- ----------
         1          1 I am                             4
         1          2 dumb                             4
         1          3 using                            5
         1          4 SQL                              3
         2          1 This is                          7
         2          2 a test                           6
         2          3 of row                           6
         2          4 2                                1

8 rows selected.