2012-05-08 14 views
3

私はまだOracleファイルのクリーンアップに取り組んでいます。ファイル内の関数/プロシージャ/パッケージ名の前にOracleスキーマ名が付加されているファイルの文字列を置き換える必要があります。関数/プロシージャ/パッケージ名は二重引用符で囲まれています。定義が修正されると、実際のコードの残りの部分とともに、ファイルに修正を書き戻します。アンカーワード間の文字列をキャプチャするPerlの正規表現

私は単純な宣言(入出力パラメータなし)を置き換えるように書かれたコードを持っています今、私は正規表現を操作しようとしています(注:この記事は続きですthis question)クリーンアップ:

置き換えます

CREATE OR REPLACE FUNCTION "TRON2000"."DC_F_DUMP_CSV_MMA" (
p_trailing_separator IN BOOLEAN DEFAULT FALSE, 
p_max_linesize IN NUMBER DEFAULT 32000, 
p_mode IN VARCHAR2 DEFAULT 'w' 
) 
RETURN NUMBER 
IS 

CREATE OR REPLACE FUNCTION DC_F_DUMP_CSV_MMA (
p_trailing_separator IN BOOLEAN DEFAULT FALSE, 
p_max_linesize IN NUMBER DEFAULT 32000, 
p_mode IN VARCHAR2 DEFAULT 'w' 
) 
RETURN NUMBER 
IS 

に私はドを分離するために、次の正規表現を使用しようとしています私はスキーマ名を削除した後の再構築のために/関数/プロシージャ/パッケージの名前を二重引用符で囲まないように修正しました。私は、バッファにそれぞれを得るに苦労しています - ここではそれ自身のバッファにすべての中間の入力/出力をつかむために私の最新の試みです:

\b(CREATE\sOR\sREPLACE\s(PACKAGE|PACKAGE\sBODY|PROCEDURE|FUNCTION))(?:\W+\w+){1,100}?\W+(RETURN)\s*(\W+\w+)\s(AS|IS)\b 

どれ/すべてのヘルプは大歓迎です!

これは私が修正されたファイルの書き込み/評価するために、今使っているスクリプトです:

#!/usr/bin/perl 
use strict; 
use warnings; 
use File::Find; 
use Data::Dumper; 

# utility to clean strings 
sub trim($) { 
    my $string = shift; 
    $string = "" if !defined($string); 

    $string =~ s/^\s+//; 
    $string =~ s/\s+$//; 

    # aggressive removal of blank lines 
    $string =~ s/\n+/\n/g; 
    return $string; 
} 

sub cleanup_packages { 
    my $file = shift; 
    my $tmp = $file . ".tmp"; 
    my $package_name; 

    open(OLD, "< $file") or die "open $file: $!"; 
    open(NEW, "> $tmp") or die "open $tmp: $!"; 

    while (my $line = <OLD>) { 

    # look for the first line of the file to contain a CREATE OR REPLACE STATEMENT 
     if ($line =~ 
m/^(CREATE\sOR\sREPLACE)\s*(PACKAGE|PACKAGE\sBODY)?\s(.+)\s(AS|IS)?/i 
     ) 
     { 

      # look ahead to next line, in case the AS/IS is next 
      my $nextline = <OLD>; 

      # from the above IF clause, the package name is in buffer 3 
      $package_name = $3; 

      # if the package name and the AS/IS is on the same line, and 
      # the package name is quoted/prepended by the TRON2000 schema name 
      if ($package_name =~ m/"TRON2000"\."(\w+)"(\s*|\S*)(AS|IS)/i) { 
       # grab just the name and the AS/IS parts 
       $package_name =~ s/"TRON2000"\."(\w+)"(\s*|\S*)(AS|IS)/$1 $2/i; 
       trim($package_name); 
      } 
      elsif ( ($package_name =~ m/"TRON2000"\."(\w+)"/i) 
        && ($nextline =~ m/(AS|IS)/)) 
      { 

# if the AS/IS was on the next line from the name, put them together on one line 
       $package_name =~ s/"TRON2000"\."(\w+)"(\s*|\S*)/$1/i; 
       $package_name = trim($package_name) . ' ' . trim($nextline); 
       trim($package_name); # remove trailing carriage return 
      } 

      # now put the line back together 
      $line =~ 
s/^(CREATE\sOR\sREPLACE)\s*(PACKAGE|PACKAGE\sBODY|FUNCTION|PROCEDURE)?\s(.+)\s(AS|IS)?/$1 $2 $package_name/ig; 

      # and print it to the file 
      print NEW "$line\n"; 
     } 
     else { 

      # just a normal line - print it to the temp file 
      print NEW $line or die "print $tmp: $!"; 
     } 
    } 

    # close up the files 
    close(OLD) or die "close $file: $!"; 
    close(NEW) or die "close $tmp: $!"; 

    # rename the temp file as the original file name 
    unlink($file) or die "unlink $file: $!"; 
    rename($tmp, $file) or die "can't rename $tmp to $file: $!"; 
} 

# find and clean up oracle files 
sub eachFile { 
    my $ext; 
    my $filename = $_; 
    my $fullpath = $File::Find::name; 

    if (-f $filename) { 
     ($ext) = $filename =~ /(\.[^.]+)$/; 
    } 
    else { 

     # ignore non files 
     return; 
    } 

    if ($ext =~ /(\.spp|\.sps|\.spb|\.sf|\.sp)/i) { 
     print "package: $filename\n"; 
     cleanup_packages($fullpath); 
    } 
    else { 
     print "$filename not specified for processing!\n"; 
    } 
} 

MAIN: 
{ 
    my (@files, $file); 
    my $dir = 'C:/1_atest'; 

    # grab all the files for cleanup 
    find(\&eachFile, "$dir/"); 

    #open and evaluate each 
    foreach $file (@files) 
    { 
     # skip . and .. 
     next if ($file =~ /^\.$/); 
     next if ($file =~ /^\.\.$/); 
      cleanup_file($file); 
     }; 
} 

答えて

3

ファイルの全内容は、VARにスカラとして格納されていると仮定すると、次のように行う必要がありますトリック。

$Str = ' 
CREATE OR REPLACE FUNCTION "TRON2000"."DC_F_DUMP_CSV_MMA" (
    p_trailing_separator IN BOOLEAN DEFAULT FALSE, 
    p_max_linesize IN NUMBER DEFAULT 32000, 
    p_mode IN VARCHAR2 DEFAULT w 
) 
RETURN NUMBER 
IS 

CREATE OR REPLACE FUNCTION "TRON2000"."DC_F_DUMP_CSV_MMA" (
    p_trailing_separator IN BOOLEAN DEFAULT FALSE, 
    p_max_linesize IN NUMBER DEFAULT 32000, 
    p_mode IN VARCHAR2 DEFAULT w 
) 
RETURN NUMBER 
IS 
'; 

$Str =~ s#^(create\s+(?:or\s+replace\s+)?\w+\s+)"[^"]+"."([^"]+)"#$1 $2#mig; 

print $Str; 
+0

素晴らしい@tuxuday!非常に効率的で、はるかに少ない複雑さ - ありがとう!私は現在、私が掃除が必要な文字列が 'TRON2000.DC_F_DUMP_CSV_MMA'から' DC_F_DUMP_CSV_MMA'(スキーマ名は存在しますが、二重引用符はありません)の私の他のケースに対して少し修正しようとします。ありがとうございました! –

関連する問題