你肯定需要一个解析器来完成这个任务。我为Vorax 创建了一个plsql 解析器,如果你愿意,可以使用它。它不是一个成熟的解析器,但足够聪明,可以弄清楚 plsql 代码的结构。
从 github 获取 vorax4 项目。
cd C:\Projects
git clone https://github.com/talek/vorax4
gem install vorax
编写一个简单的 ruby 代码来处理您的场景:
$LOAD_PATH << 'C:/Projects/vorax4/vorax/ruby/lib/'
require 'vorax.rb'
include Vorax
# You need to get this from your database
package_source =<<EOF
package body my_pck is
procedure proc1
is
v_var varchar2(10);
procedure sub_proc
is
begin
some code ....
end;
begin
some code ....
begin
anon block ....
end;
end;
procedure proc2
is
v_var varchar2(10);
procedure sub_proc_something_else
is
begin
some code ....
end;
procedure sub_proc_another
is
begin
some code ....
end;
begin
some code ....
end;
end;
EOF
structure = Parser::PlsqlStructure.new(package_source)
# just print the structure of the package
puts structure.dump
# the code we want to insert
offset = 0
INSERT_CODE = "\n--my code\n"
INSERT_CODE_LEN = INSERT_CODE.length
# loop into the plsql structure
structure.regions.each do |child|
region = child.content
# only if it's a procedure/function declared into the body of the package
if region && child.level == 2 && region.instance_of?(Parser::SubprogRegion)
pos_to_insert = offset + region.body_start_pos + 'begin'.length
# insert the code after the BEGIN clause
package_source.insert(pos_to_insert, INSERT_CODE)
# adjust the offset
offset += INSERT_CODE_LEN + 1
end
end
# print the new version of the package
puts package_source
输出是:
[Level: 0]
[Level: 1] PackageBodyRegion: {:start_pos=>2, :end_pos=>467, :name=>"my_pck", :name_pos=>15, :signature_end_pos=>24, :declare_end_pos=>462}
[Level: 2] SubprogRegion: {:start_pos=>27, :end_pos=>217, :name=>"proc1", :name_pos=>37, :body_start_pos=>145}
[Level: 3] SubprogRegion: {:start_pos=>77, :end_pos=>141, :name=>"sub_proc", :name_pos=>87, :body_start_pos=>107}
[Level: 3] AnonymousRegion: {:start_pos=>175, :end_pos=>210}
[Level: 2] SubprogRegion: {:start_pos=>221, :end_pos=>462, :name=>"proc2", :name_pos=>231, :body_start_pos=>432}
[Level: 3] SubprogRegion: {:start_pos=>271, :end_pos=>350, :name=>"sub_proc_something_else", :name_pos=>281, :body_start_pos=>316}
[Level: 3] SubprogRegion: {:start_pos=>356, :end_pos=>428, :name=>"sub_proc_another", :name_pos=>366, :body_start_pos=>394}
package body my_pck is
procedure proc1
is
v_var varchar2(10);
procedure sub_proc
is
begin
some code ....
end;
begin
--my code
some code ....
begin
anon block ....
end;
end;
procedure proc2
is
v_var varchar2(10);
procedure sub_proc_something_else
is
begin
some code ....
end;
procedure sub_proc_another
is
begin
some code ....
end;
begin
--my code
some code ....
end;
end;
其他解析器选项,虽然我没有使用过,但可能是: