Regex Can Oracle';s正则表达式子字符串用于检索;";单词在另一个字符串之前还是之后?

Regex Can Oracle';s正则表达式子字符串用于检索;";单词在另一个字符串之前还是之后?,regex,oracle,Regex,Oracle,我已经编写了两个可以工作的函数,但我相信可能有更好(更快、更优雅)的方法,在Oracle中使用正则表达式 这两个函数将在字符串中找到一个位置,该位置在前面是“n”个单词,第二个函数将在后面找到“n”个单词的位置。它们看起来像这样 FUNCTION FIND_POS_WORD_N_BEFORE(IN_WORD_POS IN BINARY_INTEGER, NUMBER_OF_WORDS_BACK IN BINARY_INTEGER, IN_STRING IN VARCHAR2) RETURN

我已经编写了两个可以工作的函数,但我相信可能有更好(更快、更优雅)的方法,在Oracle中使用正则表达式

这两个函数将在字符串中找到一个位置,该位置在前面是“n”个单词,第二个函数将在后面找到“n”个单词的位置。它们看起来像这样

  FUNCTION FIND_POS_WORD_N_BEFORE(IN_WORD_POS IN BINARY_INTEGER, NUMBER_OF_WORDS_BACK IN BINARY_INTEGER, IN_STRING IN VARCHAR2) RETURN BINARY_INTEGER DETERMINISTIC
  IS
    CURRENT_POS BINARY_INTEGER := 0;
    LOOP_COUNT BINARY_INTEGER := 0;
    OUT_POS BINARY_INTEGER := 0;

  BEGIN
    WHILE CURRENT_POS + 1 < IN_WORD_POS OR (LOOP_COUNT > 0 AND CURRENT_POS = 0)
    LOOP
      LOOP_COUNT := LOOP_COUNT + 1;
      CURRENT_POS := INSTR(IN_STRING,' ',1,LOOP_COUNT);
      IF LOOP_COUNT > NUMBER_OF_WORDS_BACK
      THEN
        OUT_POS := INSTR(IN_STRING,' ',1,LOOP_COUNT-NUMBER_OF_WORDS_BACK);
      END IF;
    END LOOP;
    RETURN OUT_POS + 1;
  END FIND_POS_WORD_N_BEFORE;

  FUNCTION FIND_POS_WORD_N_AFTER(IN_WORD_END_POS IN BINARY_INTEGER, NUMBER_OF_WORDS_AFTER IN BINARY_INTEGER, IN_STRING IN VARCHAR2) RETURN BINARY_INTEGER DETERMINISTIC
  IS
    CURRENT_POS BINARY_INTEGER := IN_WORD_END_POS;
    LOOP_COUNT BINARY_INTEGER := 0;
    OUT_POS BINARY_INTEGER := LENGTH(IN_STRING);

  BEGIN
    WHILE (LOOP_COUNT < NUMBER_OF_WORDS_AFTER + 1)
    LOOP
      LOOP_COUNT := LOOP_COUNT + 1;
      CURRENT_POS := INSTR(IN_STRING,' ',IN_WORD_END_POS,LOOP_COUNT) - 1;
    END LOOP;
    IF LOOP_COUNT >= NUMBER_OF_WORDS_AFTER  AND CURRENT_POS != -1
    THEN
      OUT_POS := CURRENT_POS;
    END IF;
    RETURN OUT_POS;
  END FIND_POS_WORD_N_AFTER;
其中:测试字符串为

this is a test of a moderately long group of words
它会回来

test of a 

我希望有人对Oracle regexp_substr非常熟悉,能够将其作为一行代码来编写。

好的,我想我理解您的要求:给定一个字符串,指定一个位置或一个单词,并在该单词之后或之前指定预定义的单词数

让我们假设输入字符串:
这是对一组中等长度的单词的测试。
我假设这些单词只包含字母数字字符和下划线。
我假设单词之间用空格隔开

警告:我认为您的函数将比使用正则表达式更有效

案例1:在单词之前 如果你想让句子中
前面的3个词适当地
,那么你可以使用:

(?:\w+|\s){6}(?=moderately)
       ^^  ^^^   ^^^^^^^^^^^
       | double number| of words you need
       |              |
       |          the word you want to look before
      the separator, if there is more than one possible type of separator then
      put them in character class like this: [\s;REST_OF_SEPARATORS]
(?<=long)(?:\w+|\s){4}
您可以使用Oracle的连接运算符或任何适当的方法,在正则表达式字符串中插入字数和要搜索的字数

案例2:在单词之后 如果你想在句子中的
long
后面找到这两个单词,你可以使用:

(?:\w+|\s){6}(?=moderately)
       ^^  ^^^   ^^^^^^^^^^^
       | double number| of words you need
       |              |
       |          the word you want to look before
      the separator, if there is more than one possible type of separator then
      put them in character class like this: [\s;REST_OF_SEPARATORS]
(?<=long)(?:\w+|\s){4}

(?这将为您提供所需单词前后的三个单词

REGEXP_SUBSTR (source_string, '([^ ]+ +){3}moderately( +[^ ]+){3}')

首先感谢您的帮助,特别是突出显示正则表达式部分。我将很快试用。但我有一个问题,为什么您认为我的例程可能比regexp_substr快?我知道正则表达式可能很慢,但比我混乱的代码慢?@PaulStearns我还没有深入研究您的代码,但我认为它会be更快,因为Oracle正则表达式引擎使用POSIX标准,因此它将始终尝试查找最长的匹配项,并使用我提供的表达式,尤其是这部分
(?:\w+\s){4}
将重复应用于
+
操作符。无论如何,我没有做任何基准测试,这是一个胡乱猜测,因此我可能完全错了,我只是想抛出一个警告,以便您注意。