2016-04-22 6 views
0

列を複数の行に分割する必要があります。列には文字列が格納されており、区切り文字を分割する必要があります。'/n'SQL区切り文字 '/ n'に基づいて列(文字列)を複数の行に分割する正規表現

以下の文章を書いてあります。しかし、^[/n]を指定することはできません。文字列の他の'n'も削除されています。 と '[^/N] +' のいずれか構文的に良くありませんあなたは[::CNTRL] []は、クラスを使用する必要がある文字列

WITH sample AS 
(SELECT 101 AS id, 
     'Name' test, 
     '3243243242342342/n12131212312/n123131232/n' as attribute_1, 
     'test value/nneenu not/nhoney' as attribute_2 
    FROM DUAL 
) 
-- end of sample data 
SELECT id, 
     test, 
     regexp_substr(attribute_1,'[^/n]+', 1, column_value), 
     regexp_substr(attribute_2,'[^/]+', 1, column_value) 
    FROM sample, 
     TABLE(
     CAST(
      MULTISET(SELECT LEVEL 
         FROM dual 
        CONNECT BY LEVEL <= LENGTH(attribute_1) - LENGTH(replace(attribute_1, '/n')) + 1 
        ) AS sys.OdciNumberList 
     ) 
     ) 
WHERE regexp_substr(attribute_1,'[^/n]+', 1, column_value) IS NOT NULL 
/
+1

文字列 '/ n'を分割する必要がありますか、新しい行ですか? – Aleksej

+0

こんにちは、あなたは[[:cntrl:]]クラス – Thomas

+0

と '[^/n] +'のどちらも構文的には良いとは思わないと思っています。 – Thomas

答えて

0

を解析するために助けてください。

エスケープ文字は「\」であると、あなたの代わりに)(を使用する必要がありますが、特殊文字を「ラップ」するために[]を使用することはできません。(それがグループ化された)

あなたはCRを無視したい場合(たとえば、」 \ n 'の)は、[^ [:CNTRL:]] REGEXP_SUBSTRで秒のparamで

より多くのヘルプ:http://psoug.org/snippet/Regular-Expressions--Regexp-Cheat-Sheet_856.htm

+0

Nitpicking: '\ n'は' CR'ではなく 'LF'を表します。 ( '\ r'になります)。出典:other、yours ...;) – collapsar

0

昇天

/nは、改行(厳密に[Posix] LF文字(hex x0a)を話す)と一致するように\nを意味するものとします。

この仮定が間違っている場合は、(^|/n)(([^/]|/+[^n])+)を正規表現として使用し、regexp_substr(attribute_1,'(^|/n)(([^/]|/+[^n])+)', 1, column_value, '', 2)を使用して対象部分を抽出します。

ソリューション

あなたは、文字クラス内のエスケープ構文で制御文字を指定することはできません。 posix文字クラス[:cntrl:]を使用すると、他の文字が含まれています。実際の目的のために、TAB(#x09)は迷惑であるかもしれません。

しかし、あなたはchr関数にリテラルと呼び出しからパターン文字列を構成する正規表現文字クラス内のすべての文字を指定することができます。

-- ... 
    '3243243242342342'||chr(13)||chr(10)||'12131212312'||chr(13)||chr(10)||'123131232'||chr(13)||chr(10) as attribute_1, 
    'test value'||chr(13)||chr(10)||'neenu not'||chr(13)||chr(10)||'honey' as attribute_2 
    -- ... 
    regexp_substr(attribute_1,'[^'||chr(13)||chr(10)||']+', 1, column_value), 
    regexp_substr(attribute_2,'[^'||chr(13)||chr(10)||']+', 1, column_value) 
    -- ... 

あなたはSQLPLUSで、次のテストのクエリをチェックアウトすることができます( CR/LFSは、リテラルの一部であり、再挿入しない場合は、SQLPLUSで結果をドロップし、CR/LFSは保存されていることを確認し、テキストエディタにコピー):

select regexp_substr('adda 
yxcv','[^'||CHR(10)||CHR(13)||']+', 1, 2) from dual; 
select regexp_substr('ad'||CHR(9)||'da 
yxcv','[^[:cntrl:]]+', 1, 2) from dual; 
+0

OPのテストデータには実際には '/ n'がありますが、' \ n'ではありません。私はそれにも非常に驚いていますが、それがOPのテストデータの間違いだと思うなら、答えにそう言います。 – hvd

+0

@hvdはい、あなたは正しいです - 私は暗黙のうちにこれがデータとパターンの中でミスペルトされていると仮定しました。それに応じて答えを変更します。 – collapsar

0
with test as (select 'ABC' || chr(13) || 'DEF' || chr(13) || 'GHI' || chr(13) || 'JKL' || chr(13) || 'MNO' str from dual) 
select regexp_substr (str, '[^' || chr(13) || ']+', 1, rownum) split 
from test 
connect by level <= length (regexp_replace (str, '[^' || chr(13) || ']+')) + 1 
0

この方法で保存されたデータは最適ではないため、データモデルを修正することをお勧めします。とにかく、テストデータを追加してこのバージョンを試してみてください。私は正規表現を微調整しました:

WITH sample AS 
(SELECT 101 AS id, 
     'Name' test, 
     '3243243242342342/n12131212312/n123131232/n' as attribute_1, 
     'test value/nneenu not/nhoney' as attribute_2 
    FROM DUAL 
) 
-- end of sample data 
SELECT id, 
     test, 
     regexp_substr(attribute_1,'(.*?)(/n|$)', 1, column_value, NULL, 1), 
     regexp_substr(attribute_2,'(.*?)(/n|$)', 1, column_value, NULL, 1) 
    FROM sample, 
     TABLE(
     CAST(
      MULTISET(SELECT LEVEL 
         FROM dual 
        --CONNECT BY LEVEL <= LENGTH(attribute_1) - LENGTH(replace(attribute_1, '/n')) + 1 
         -- Counts substrings ending with the delimiter. 
         CONNECT BY LEVEL <= REGEXP_COUNT(attribute_1, '.*?/n')      
        ) AS sys.OdciNumberList 
     ) 
     ) 
WHERE regexp_substr(attribute_1,'(.*?)(/n|$)', 1, column_value, NULL, 1) IS NOT NULL 
/