well, if your coding standards are like that (nice - very uniform), then
ops$tkyte%ORA11GR2> select rec_name, field_name
2 from (
3 select text,
4 line,
5 rec_name,
6 case when row_number() over (partition by max_tag order by line) > 1
7 then substr( ltrim( ltrim( text, ' ' ), ',' ), 1, instr( ltrim(ltrim(text, ' ' ), ','), ' ')-1 )
8 end field_name,
9 max_tag,
10 lv_keep_flag,
11 row_number() over (partition by max_tag order by line) rn
12 from (
13 select text,
14 line,
15 max(tag) over (order by line) max_tag,
16 last_value(record_name ignore nulls) over (order by line) rec_name,
17 last_value(keep_flag ignore nulls) over (order by line) lv_keep_flag
18 from (
19 select line,
20 text ,
21 case when text like '%TYPE % IS %RECORD %(%'
22 then substr( text, instr(text,'TYPE ')+5, instr( text, ' IS ')-instr( text, 'TYPE ')-5 )
23 end record_name,
24 case when text like '%TYPE % IS %RECORD %(%'
25 then row_number() over (order by line)
26 when lag(text) over (order by line) like '%);%'
27 then row_number() over (order by line)
28 end tag,
29 case when text like '%TYPE % IS %RECORD %(%'
30 then 1
31 when lag(text) over (order by line) like '%);%'
32 then 0
33 end keep_flag
34 from user_source
35 where name = 'TEST_PK_SPECS'
36 and type = 'PACKAGE'
37 and replace( text, ' ', '' ) NOT like '--%'
38 )
39 )
40 where lv_keep_flag = 1
41 )
42 where rn > 1
43 order by line;
REC_NAME FIELD_NAME
--------------- ---------------
rcd_emp_code id_type
rcd_emp_code emp_code
rcd_emp_code id_version
rcd_emp_code create_date
rcd_dept_code id_type
rcd_dept_code dept_code
rcd_dept_code dept_city
7 rows selected.