2014-07-06 47 views
0

我想解析對SYBASE服務器運行prsqlcache命令的輸出並將輸出信息存儲到表中。每個列信息都存儲爲標量並保存到一個數組中,然後將整個數組BCP輸入到目標表中。正則表達式給出不正確的輸出

作爲一個示例,我給出了兩個緩存語句的輸出示例。在第一條語句緩存信息中,SQL文本包含我嘗試提取的列的名稱,因此,當我使用我編寫的代碼時,由於每個SSQL_DESC,ssql_name等出現不止一個匹配項,因此它會中斷。

最簡單的解決方案是刪除包含SQL文本的行,我想要查找並刪除它,因爲我不需要這些信息。但事實證明我也需要這個。有沒有辦法使我的現有邏輯工作?

輸入文件樣本

Start of SSQL Hash Table at 0x0x2aacbdfdf050 
Memory configured: 1024000 2k pages Memory used: 109219 2k pages 
Bucket# 000 address 0x0x2aacbdfdf050 
SSQL_DESC 0x0x2aad268cb8b0 
ssql_name *ss1530075878_1111638016ss* 
ssql_hashkey 0x0x42424000 ssql_id 1530075878 
ssql_suid 31838  ssql_uid 1063880 ssql_dbid 14 ssql_spid 0 
ssql_status 0x0x81 ssql_parallel_deg 1 
ssql_isolate 1  ssql_tranmode 32 
ssql_keep 0  ssql_usecnt 1 ssql_pgcount 20 
ssql_optgoal allrows_oltp ssql_optlevel ase_default 
opt options bitmap 00809f172c6181fffb160500008009000000000000000000000000000000 
SQL TEXT: select SSQL_DESC = 'addadads',ssql_name='aasass', ssql_hashkey='ssdddssddcs', ssql_id =1345, ssql_suid =4344, ssql_uid =2344, ssql_dbid=11, ssql_spid=0,ssql_status=0x024, ssql_parallel_deg=1, ssql_isolate = 1, ssql_tranmode = 32, ssql_keep = 1, ssql_usecnt =9, ssql_pgcount =8, ssql_optgoal = 'allrows', ssql_optlevel ='wee', opt = 'options', bitmap = '1235ddf3445553334' from table1 
SSQL_DESC 0x0x2aad268cb8b0 
ssql_name *ss1530075878_1111638016ss* 
ssql_hashkey 0x0x433424030 ssql_id 1443475244 
ssql_suid 553 ssql_uid 1443 ssql_dbid 15 ssql_spid 1 
ssql_status 0x0x22 ssql_parallel_deg 1 
ssql_isolate 1  ssql_tranmode 62 
ssql_keep 0  ssql_usecnt 1 ssql_pgcount 22 
ssql_optgoal allrows_oltp ssql_optlevel ase_default 
opt options bitmap 00809f172c6181fffb160500008009000000000000000000000000000000 
SQL TEXT: select column from table 

代碼片段

foreach my $line (@file){ 
    #print $line; 
    my $string = "SSQL_DESC"; 
    my $string1 = "ssql_name"; 
    my $string2 ="ssql_hashkey"; 
    my $string3 = "ssql_suid"; 
    my $string4 = "ssql_status"; 
    my $string5 = "ssql_isolate"; 
    my $string6 = "ssql_keep"; 
    my $string7 = "ssql_optgoal"; 
    my $string8 = "bitmap"; 

    if ($line =~ /$string/i) { 
     my @sentence = split ' ', $line; 
     $sql_desc = $sentence[1]; 
    } 

    if ($line =~ /$string1/i) { 
     my @sentence = split ' ', $line; 
     $sql_name = $sentence[1]; 
    } 

    if ($line =~ /$string2/i) { 
     my @sentence = split ' ', $line; 
     $sql_hashkey = $sentence[1]; 
     $ssql_id = $sentence[3]; 

     print Dumper \@sentence; 
    } 

    if($line =~ /$string3/i){ 
     my @sentence = split ' ', $line; 
     $ssql_suid = $sentence[1]; 
     $ssql_uid = $sentence[3]; 
     $ssql_dbid = $sentence[5]; 
     $ssql_spid = $sentence[7]; 
    } 

    if($line =~ /$string4/i){ 
     my @sentence = split ' ', $line; 
     $ssql_status = $sentence[1]; 
     $ssql_parallel_deg = $sentence[3]; 
    } 

    if($line =~ /$string5/i){ 
     my @sentence = split ' ', $line; 
     $ssql_isolate = $sentence[1]; 
     $ssql_tranmode = $sentence[3]; 
    } 

    if($line =~ /$string6/i){ 
     my @sentence = split ' ', $line; 
     $ssql_keep = $sentence[1]; 
     $ssql_usecnt = $sentence[3]; 
     $ssql_pgcount = $sentence[5]; 
    } 

    if($line =~ /$string7/i){ 
     my @sentence = split ' ', $line; 
     $ssql_optgoal = $sentence[1]; 
     $ssql_optlevel = $sentence[3]; 
    } 

    if ($line =~ /$string8/i) { 
     my @sentence = split ' ', $line; 
     $ssql_opt = $sentence[1]; 
     $bitmap = $sentence[3]; 

     @array = ($sql_desc, $sql_name, $sql_hashkey, $ssql_id, $ssql_suid, $ssql_uid, $ssql_dbid, $ssql_spid, $ssql_status, $ssql_parallel_deg, $ssql_isolate, $ssql_tranmode, $ssql_keep, $ssql_usecnt, $ssql_pgcount, $ssql_optgoal, $ssql_optlevel, $ssql_opt, $bitmap); 
     #print Dumper \@array; 
    } 

} 

輸出:

$VAR1 = [ 
      'ssql_hashkey', 
      '0x0x42424000', 
      'ssql_id', 
      '1530075878' 
     ]; 
$VAR1 = [ 
      'SQL', 
      'TEXT:', 
      'select', 
      'SSQL_DESC', 
      '=', 
      '\'addadads\',ssql_name=\'aasass\',', 
      'ssql_hashkey=\'ssdddssddcs\',', 
      'ssql_id', 
      '=1345,', 
      'ssql_suid', 
      '=4344,', 
      'ssql_uid', 
      '=2344,', 
      'ssql_dbid=11,', 
      'ssql_spid=0,ssql_status=0x024,', 
      'ssql_parallel_deg=1,', 
      'ssql_isolate', 
      '=', 
      '1,', 
      'ssql_tranmode', 
      '=', 
      '32,', 
      'ssql_keep', 
      '=', 
      '1,', 
      'ssql_usecnt', 
      '=9,', 
      'ssql_pgcount', 
      '=8,', 
      'ssql_optgoal', 
      '=', 
      '\'allrows\',', 
      'ssql_optlevel', 
      '=\'wee\',', 
      'opt', 
      '=', 
      '\'options\',', 
      'bitmap', 
      '=', 
      '\'1235ddf3445553334\'', 
      'from', 
      'table1' 
     ]; 
$VAR1 = [ 
      'ssql_hashkey', 
      '0x0x433424030', 
      'ssql_id', 
      '1443475244' 
     ]; 
+0

使數組引用或數組引用的散列的數組,每當你得到'$ string8'也許'SQL TEXT',添加當前數組你構建數組引用的數組/散列並開始構建新的數組。 – chilemagic

+0

是的,@Borodin確實爲您提到的內容提供瞭解決方案。我玩弄瞭解決方案,現在我開始更多地理解哈希。我覺得這對我來說是一個很好的開始,因爲我是Perl新手,而不是程序員。:) – RingMaster

回答

1

無論何時你發現你自己寫很多標量聲明都要以類似的方式使用,那麼你應該考慮立即使用散列。這同樣適用於一系列變量,其名稱除末尾的索引號外全部相同:這些變量應爲數組

處理這個問題的最好方法是將SQL TEXT行作爲特例處理。它也很有用,因爲它始終是每個塊的最後一行,因此可以用作轉儲迄今爲止發現的數據的觸發器。

我已經使用數組@fields來包含所有要提取的字段的名稱。推導出與join 012xx交替操作符的管道join相匹配的任何字段名的正則表達式很簡單。

此後,只需要在文件的每一行中查找所有出現的任何字段名稱,並提取以下數據字段。所有這些都存儲在散列表%data中。

我硬編ssql_opt"bitmap",因爲它似乎總是相同的。如果這是錯誤的,那麼你必須解釋如何從文件中獲得它的價值。我懷疑,實際上,可能會有值,並且您將不得不重新考慮如何表示這些值。

我還沒有重建您的最終@array,因爲它不清楚它只是一個調試工件。如果你需要它,那麼它只是my @array = @data{@fields}

use strict; 
use warnings; 
use 5.010; 

use Data::Dump; 

my @fields = qw/ 
    SSQL_DESC 
    ssql_name 
    ssql_hashkey  ssql_id 
    ssql_suid   ssql_uid   ssql_dbid   ssql_spid 
    ssql_status  ssql_parallel_deg 
    ssql_isolate  ssql_tranmode 
    ssql_keep   ssql_usecnt  ssql_pgcount 
    ssql_optgoal  ssql_optlevel 
    bitmap 
/; 

my $re = join '|', @fields; 
my %data; 

while (my $line = <DATA>) { 

    if ($line =~ /^(SQL TEXT):\s*(.*)/) { 

    $data{$1} = $2; 

    $data{ssql_opt} = "bitmap"; 
    printf "%-20s => %s\n", $_, $data{$_} // '<undef>' for @fields; 
    print "$1: $2\n"; 
    print "\n"; 

    %data =(); 
    } 
    else { 
    $data{$1} = $2 while $line =~ /\b($re)\s+(\S+)/og; 
    } 
} 

__DATA__ 
Start of SSQL Hash Table at 0x0x2aacbdfdf050 
Memory configured: 1024000 2k pages Memory used: 109219 2k pages 
Bucket# 000 address 0x0x2aacbdfdf050 

SSQL_DESC 0x0x2aad268cb8b0 
ssql_name *ss1530075878_1111638016ss* 
ssql_hashkey 0x0x42424000 ssql_id 1530075878 
ssql_suid 31838  ssql_uid 1063880 ssql_dbid 14 ssql_spid 0 
ssql_status 0x0x81 ssql_parallel_deg 1 
ssql_isolate 1  ssql_tranmode 32 
ssql_keep 0  ssql_usecnt 1 ssql_pgcount 20 
ssql_optgoal allrows_oltp ssql_optlevel ase_default 
opt options bitmap 00809f172c6181fffb160500008009000000000000000000000000000000 
SQL TEXT: select SSQL_DESC = 'addadads',ssql_name='aasass', ssql_hashkey='ssdddssddcs', ssql_id =1345, ssql_suid =4344, ssql_uid =2344, ssql_dbid=11, ssql_spid=0,ssql_status=0x024, ssql_parallel_deg=1, ssql_isolate = 1, ssql_tranmode = 32, ssql_keep = 1, ssql_usecnt =9, ssql_pgcount =8, ssql_optgoal = 'allrows', ssql_optlevel ='wee', opt = 'options', bitmap = '1235ddf3445553334' from table1 

SSQL_DESC 0x0x2aad268cb8b0 
ssql_name *ss1530075878_1111638016ss* 
ssql_hashkey 0x0x433424030 ssql_id 1443475244 
ssql_suid 553 ssql_uid 1443 ssql_dbid 15 ssql_spid 1 
ssql_status 0x0x22 ssql_parallel_deg 1 
ssql_isolate 1  ssql_tranmode 62 
ssql_keep 0  ssql_usecnt 1 ssql_pgcount 22 
ssql_optgoal allrows_oltp ssql_optlevel ase_default 
opt options bitmap 00809f172c6181fffb160500008009000000000000000000000000000000 
SQL TEXT: select column from table 

輸出

SSQL_DESC   => 0x0x2aad268cb8b0 
ssql_name   => *ss1530075878_1111638016ss* 
ssql_hashkey   => 0x0x42424000 
ssql_id    => 1530075878 
ssql_suid   => 31838 
ssql_uid    => 1063880 
ssql_dbid   => 14 
ssql_spid   => 0 
ssql_status   => 0x0x81 
ssql_parallel_deg => 1 
ssql_isolate   => 1 
ssql_tranmode  => 32 
ssql_keep   => 0 
ssql_usecnt   => 1 
ssql_pgcount   => 20 
ssql_optgoal   => allrows_oltp 
ssql_optlevel  => ase_default 
ssql_opt    => bitmap 
bitmap    => 00809f172c6181fffb160500008009000000000000000000000000000000 
SQL TEXT: select SSQL_DESC = 'addadads',ssql_name='aasass', ssql_hashkey='ssdddssddcs', ssql_id =1345, ssql_suid =4344, ssql_uid =2344, ssql_dbid=11, ssql_spid=0,ssql_status=0x024, ssql_parallel_deg=1, ssql_isolate = 1, ssql_tranmode = 32, ssql_keep = 1, ssql_usecnt =9, ssql_pgcount =8, ssql_optgoal = 'allrows', ssql_optlevel ='wee', opt = 'options', bitmap = '1235ddf3445553334' from table1 

SSQL_DESC   => 0x0x2aad268cb8b0 
ssql_name   => *ss1530075878_1111638016ss* 
ssql_hashkey   => 0x0x433424030 
ssql_id    => 1443475244 
ssql_suid   => 553 
ssql_uid    => 1443 
ssql_dbid   => 15 
ssql_spid   => 1 
ssql_status   => 0x0x22 
ssql_parallel_deg => 1 
ssql_isolate   => 1 
ssql_tranmode  => 62 
ssql_keep   => 0 
ssql_usecnt   => 1 
ssql_pgcount   => 22 
ssql_optgoal   => allrows_oltp 
ssql_optlevel  => ase_default 
ssql_opt    => bitmap 
bitmap    => 00809f172c6181fffb160500008009000000000000000000000000000000 
SQL TEXT: select column from table 
+0

ssql_opt不是字段。位圖本身就是一個字段。在任何情況下,我絕對不想硬編碼任何值,以防SYBASE更改緩存語句輸出的結構。 SYBASE改變了輸出內容的結構,這個解決方案就是我所尋找的,而不是我的一半版本。 @array需要用於BCP進入目標表的數組。檢索所有信息,包括SQL TEXT信息並不困難。 – RingMaster

+0

@Borodin令人印象深刻的解密。 – Miller