web-dev-qa-db-ja.com

regexp_substrを使用して、Oracleで区切り文字として文字列をスペースと文字で分割します

Regexp_subtrで文字列を分割しようとしていますが、機能させることができません。

だから、最初に、私はこのクエリを持っています

select regexp_substr('Helloworld - test!' ,'[[:space:]]-[[:space:]]') from dual

これは私の区切り文字を非常にうまく抽出します-空白 -空白

しかし、このオプションを使用して文字列を分割しようとすると、機能しません。

select regexp_substr('Helloworld - test!' ,'[^[[:space:]]-[[:space:]]]+')from dual

クエリは何も返しません。

助けていただければ幸いです!ありがとう

3
aleko_vp

SQLフィドル

Oracle 11g R2スキーマセットアップ

CREATE TABLE TEST( str ) AS
          SELECT 'Hello world - test-test! - test' FROM DUAL
UNION ALL SELECT 'Hello world2 - test2 - test-test2' FROM DUAL;

クエリ1

SELECT Str,
       COLUMN_VALUE AS Occurrence,
       REGEXP_SUBSTR( str ,'(.*?)([[:space:]]-[[:space:]]|$)', 1, COLUMN_VALUE, NULL, 1 ) AS split_value
FROM   TEST,
       TABLE(
         CAST(
           MULTISET(
             SELECT LEVEL
             FROM   DUAL
             CONNECT BY LEVEL < REGEXP_COUNT( str ,'(.*?)([[:space:]]-[[:space:]]|$)' )
           )
           AS SYS.ODCINUMBERLIST
         )
       )

結果

|                               STR | OCCURRENCE |  SPLIT_VALUE |
|-----------------------------------|------------|--------------|
|   Hello world - test-test! - test |          1 |  Hello world |
|   Hello world - test-test! - test |          2 |   test-test! |
|   Hello world - test-test! - test |          3 |         test |
| Hello world2 - test2 - test-test2 |          1 | Hello world2 |
| Hello world2 - test2 - test-test2 |          2 |        test2 |
| Hello world2 - test2 - test-test2 |          3 |   test-test2 |
8
MT0

私が正しく理解していれば、これはあなたを助けるでしょう。現在、出力はHelloworld(最後にスペースがあります)として取得されています。だから私はあなたが最後にスペースを持ちたくないと思います。もしそうなら、あなたは単に同様に区切り文字のスペースを使うことができます。

select regexp_substr('Helloworld - test!' ,'[^ - ]+',1,1)from dual;

OUTPUT
Helloworld(No space at the end)

Urコメントで述べたように、Helloworldtest!で2つの列を出力する場合。次のことができます。

select regexp_substr('Helloworld - test!' ,'[^ - ]+',1,1),
       regexp_substr('Helloworld - test!' ,'[^ - ]+',1,3) from dual;

OUTPUT
col1         col2
Helloworld   test!
1
Arun Palanisamy

一致文字列_'[[:space:]]-[[:space:]]'_を曲折アクセント記号(^)を使用して文字クラスに入れて無効にしようとすると、機能しません。角括弧のペアの間のすべては、オプションの文字のリストに展開される名前付きの名前付き文字クラスを除いて、オプションの単一文字のリストとして扱われますが、文字クラスのネスト方法により、外側の括弧は次のように解釈されます:

  • _[^[[:space:]]_単一の非スペース非左角括弧文字
  • _-_の後に1つのハイフンが続く
  • _[[:space:]]_の後に単一のスペース文字が続く
  • _]+_の後に1つ以上の閉じ角括弧が続きます。

Regexp_replaceを使用して複数文字の区切り文字を単一の文字に変換してから、regex_substrを使用して個々の部分を見つける方が簡単な場合があります。

_select regexp_substr(regexp_replace('Helloworld - test!'
                                   ,'[[:space:]]-[[:space:]]'
                                   ,chr(11))
                    ,'([^'||chr(11)||']*)('||chr(11)||'|$)'
                    ,1 -- Start here
                    ,2 -- return 1st, 2nd, 3rd, etc. match
                    ,null
                    ,1 -- return 1st sub exp
                    )
  from dual;
_

このコードでは、最初に_-_をchr(11)に変更しました。これはASCII垂直タブ(VT)文字であり、ほとんどのテキスト文字列に表示される可能性は低いです。次に、regexp_substrの一致式は、すべての非VT文字に一致し、その後にVT文字またはの終わりが続きます。 line。非VT文字のみが返されます(最初の部分式)。

1
Sentinel
CREATE OR REPLACE FUNCTION field(i_string            VARCHAR2
                                ,i_delimiter         VARCHAR2
                                ,i_occurance         NUMBER
                                ,i_return_number     NUMBER DEFAULT 0
                                ,i_replace_delimiter VARCHAR2) RETURN VARCHAR2     IS
  -----------------------------------------------------------------------
  -- Function Name.......: FIELD
  -- Author..............: Dan Simson
  -- Date................: 05/06/2016 
  -- Description.........: This function is similar to the one I used from 
  --                       long ago by Prime Computer.  You can easily
  --                       parse a delimited string.
  -- Example.............: 
  --  String.............: This is a cool function
  --  Delimiter..........: ' '
  --  Occurance..........: 2
  --  Return Number......: 3
  --  Replace Delimiter..: '/'
  --  Return Value.......: is/a/cool
  --------------------------------------------------------------------------    ---                                    
  v_return_string  VARCHAR2(32767);
  n_start          NUMBER := i_occurance;
  v_delimiter      VARCHAR2(1);
  n_return_number  NUMBER := i_return_number;
  n_max_delimiters NUMBER := regexp_count(i_string, i_delimiter);
BEGIN
  IF i_return_number > n_max_delimiters THEN
    n_return_number := n_max_delimiters + 1;
  END IF;
  FOR a IN 1 .. n_return_number LOOP
    v_return_string := v_return_string || v_delimiter || regexp_substr    (i_string, '[^' || i_delimiter || ']+', 1, n_start);
    n_start         := n_start + 1;
    v_delimiter     := nvl(i_replace_delimiter, i_delimiter);
  END LOOP;
  RETURN(v_return_string);
END field;


SELECT field('This is a cool function',' ',2,3,'/') FROM dual;

SELECT regexp_substr('This is a cool function', '[^ ]+', 1, 1) Word1
      ,regexp_substr('This is a cool function', '[^ ]+', 1, 2) Word2
      ,regexp_substr('This is a cool function', '[^ ]+', 1, 3) Word3
      ,regexp_substr('This is a cool function', '[^ ]+', 1, 4) Word4
      ,regexp_substr('This is a cool function', '[^ ]+', 1, 5) Word5
  FROM dual;
0
Dan

MT0の回答がわずかに改善されました。 regexp_countを使用した動的カウントで、パターンとしての[^ delimiter] +の形式がNULLリスト要素を処理しない場合にnullを処理することを証明します。詳細については、こちらをご覧ください: カンマ区切りの値を列に分割

SQL> with tbl(str) as (
  2    select ' - Hello world - test-test! -  - test - ' from dual
  3  )
  4  SELECT LEVEL AS Occurrence,
  5         REGEXP_SUBSTR( str ,'(.*?)([[:space:]]-[[:space:]]|$)', 1, LEVEL, NULL, 1 ) AS split_value
  6  FROM   tbl
  7  CONNECT BY LEVEL <= regexp_count(str, '[[:space:]]-[[:space:]]')+1;

OCCURRENCE SPLIT_VALUE
---------- ----------------------------------------
         1
         2 Hello world
         3 test-test!
         4
         5 test
         6

6 rows selected.

SQL>
0
Gary_W