0

我知道如何使用 utl_file 从文件中读取数据,但我遇到了以下数据的问题。我们不能假设哪个位置的数据会为空。我们该如何处理呢?

样本数据:apple|bat|cat|"dog | dog"||||eee||abc

预期输出:

col1:apple
col2:bat
col3:cat
col4:dog dog
col5:
col6:
col7:
col8:eee
col9:
col10:abc

我试过下面的代码,但它没有处理空值

declare
list varchar2(3500) :='apple|bat|cat|"dog | dog"||||eee||abc';
pattern varchar2(20) := '(" [^"]*"|[^|]+)';
i number:=0;
j number;
f varchar2(3500);
 c sys_refcursor;
begin
dbms_output.put_line('Raw list: ' || list);
 open c for
             select  level as col,
                 trim(regexp_substr(replace(list,'|','|'), pattern, 1, rownum))split  
             from dual
             connect by level <= length(regexp_replace(list, pattern))  + 1;
        loop
            fetch c into j, f;
            exit when c%notfound;
            dbms_output.put_line('Column ' || i || ': ' || replace(f, '"'));
            i:=i+1;
        end loop;
        close c;

end;

我的输出低于预期,但我需要预期的输出。

原始列表:apple|bat|cat|"dog|dog"||||eee||abc
第 0 列:apple
第 1 列:bat
第 2 列:cat
第 3 列:dog
第 4 列:dog
第 5 列:eee
第 6 列:abc
第 7 栏:
第 8 栏:
第 9 栏:
第 10 栏:

4

1 回答 1

0

我不会为此使用正则表达式。

相反,我会使用普通的字符串操作函数将字符串分开。例如:

declare
    list varchar2(3500) := 'apple|bat|cat|"dog | dog"||||eee||abc';

    next_pipe_pos       integer;
    close_quote_pos     integer;
    column_start_pos    integer;
    column_num          integer;
    column_text         varchar2(4000);
begin
    column_start_pos := 1;
    column_num := 1;

    -- Appending a | character allows us to assume that all columns have a
    -- pipe following them and avoids any special-case handling for the last
    -- column.
    list := list || '|';

    while column_start_pos <= length(list)
    loop
        if substr(list, column_start_pos, 1) = '"' then
            close_quote_pos := instr(list, '"|', column_start_pos + 1);
            if close_quote_pos = 0 then
                -- Mismatched quotes.
                raise no_data_found;
            end if;

            column_text := substr(list, column_start_pos + 1, close_quote_pos - column_start_pos - 1);
            column_start_pos := close_quote_pos + 2;
        else
            next_pipe_pos := instr(list, '|', column_start_pos);
            exit when next_pipe_pos = 0;
            column_text := substr(list, column_start_pos, next_pipe_pos - column_start_pos);
            column_start_pos := next_pipe_pos + 1;
        end if;

        dbms_output.put_line('Column ' || column_num || ': ' || column_text);

        column_num := column_num + 1;        
    end loop;
end;

它的代码更多,但可以说它没有您使用的正则表达式那么神秘。

运行这个的输出:

Column 1: apple
Column 2: bat
Column 3: cat
Column 4: dog | dog
Column 5:
Column 6:
Column 7:
Column 8: eee
Column 9:
Column 10: abc
于 2014-09-07T09:51:38.163 回答