2009-09-17 28 views
-2

我有一個DOS命令,其輸出如下(只是含有3個結果爲例):如何通過Perl字符串操作獲取值?

 
The Scheme GUID: 123-abc (Scheme1) * 

The Scheme GUID: 456-def (Scheme2) 

The Scheme GUID: 789-ghi (Scheme3) 

我從Perl腳本調用所述命令行程序,我想存儲在一個結構中的兩個結果:

 
**123-abc** (alphanumeric value) & 
**Scheme1**(name of the scheme) 
*(values obtained from the results mentioned above in the eg)* 
  1. 我想知道如何存儲上述3個結果(字母數字值和方案的名稱),並投入3個結構的數組。

  2. 我需要得到已加星標的Scheme(如上面Scheme1星號所示)並將其分配給一個全局變量。

+2

我認爲你需要澄清。因爲我不知道你想完成什麼。 – 2009-09-17 18:15:55

+0

我想檢索這些字符串(字母數字值和方案名稱)從DOS命令獲得的結果.... 我需要選擇兩個(例如:<123-abc>&)frm結果那些只使用PERL字符串操作。 並且我還需要使用PERL字符串操作 和 – 2009-09-17 18:30:26

回答

4

這聽起來像是一個regexarray of hashes的工作。

首先,我們創建一個可以找到信息的模式。您正在尋找一個常量字符串"The Scheme GUID: ",後面跟着一個連續的字母數字和連字符字符串,後跟一個空格,然後是一個由括號包圍的字母數字字符的連續字符串。在正則表達式中,這是/The Scheme GUID: [a-zA-Z0-9-]+ \([a-zA-Z0-9]+\)/。現在,只會匹配的字符串,我們要拔出它的一部分,所以我們需要捕捉添加到正則表達式,趕上它的返回:

my ($guid, $scheme) = /The Scheme GUID: ([a-zA-Z0-9-]+) \(([a-zA-Z0-9]+)\)/; 

()用來表示我們想要的部分從字符串中保存並被稱爲捕獲。

現在我們有了這些值,您希望創建一個類似於記錄的結構。在Perl中,您通常使用的哈希用於此目的:

my %record = (
    guid => $guid, 
    scheme => $scheme 
); 

您現在可以訪問說$record{guid}的GUID。要建立對這些記錄的數組,只需輕輕一按記錄到一個數組:

my @records; 
while (<>) { 
    my ($guid, $scheme) = /The Scheme GUID: ([a-zA-Z0-9-]+) \(([a-zA-Z0-9])\)/; 
    my %record = (
     guid => $guid, 
     scheme => $scheme 
    ); 
    push @records, \%record; 
} 

您現在可以訪問像這樣的第三個記錄的方案:$records[2]{scheme}

您的最後一項要求需要更改正則表達式。如果你看到它,你需要尋找那顆明星並做一些特別的事情。不幸的是,星星意味着正則表達式,所以你需要像括號一樣逃避它。和明星並不總是存在,所以你需要使用非分組圓括號(?:)?量詞告訴正則表達式是不匹配的字符串的一部分是好的:

my ($guid, $scheme, $star) = /The Scheme GUID: ([a-zA-Z0-9-]+) \(([a-zA-Z0-9]+)\)(?: (\*))?/; 

正則表達式已經非常得到長,很難在​​這一點上讀,所以它可能是使用/x標誌,並添加一些空白和註釋的正則表達式是一個好主意:

my ($guid, $scheme, $star) = m{ 
    The [ ] Scheme [ ] GUID: 
    ([a-zA-Z0-9-]+)   #capture the guid 
    [ ] 
    \( ([a-zA-Z0-9]+) \) #capture the scheme 
    (?: 
     [ ] 
     (\*)    #capture the star if it exists 
    )? 
}x; 

他們這樣,我會寫一個這樣的程序是:

#!/usr/bin/perl 

use strict; 
use warnings; 

my $primary_record; 
my @records; 
while (<DATA>) { 
    next unless my ($guid, $scheme, $star) = m{ 
     The [ ] Scheme [ ] GUID: [ ] 
     ([a-zA-Z0-9-]+)   #capture the guid 
     [ ] 
     \( ([a-zA-Z0-9]+) \) #capture the scheme 
     (?: 
      [ ] 
      ([*])    #capture the star if it exists 
     )? 
    }x; 
    my %record = (
     guid => $guid, 
     scheme => $scheme, 
     starred => defined $star ? 1 : 0 
    ); 

    if ($record{starred}) { 
     $primary_record = \%record; 
    } 

    push @records, \%record; 
} 

print "records:\n"; 
for my $record (@records) { 
    print "\tguid: $record->{guid} scheme: $record->{scheme}\n"; 
} 
print "primary record is $primary_record->{guid}\n"; 

__DATA__ 
The Scheme GUID: 123-abc (Scheme1) * 
The Scheme GUID: 456-def (Scheme2) 
The Scheme GUID: 789-ghi (Scheme3) 

如果你有在數組中的數據,你可以用for循環替換while循環:

for my $line (@lines) { 
    next unless my ($guid, $scheme, $star) = $line =~ m{ 
     The [ ] Scheme [ ] GUID: [ ] 
     ([a-zA-Z0-9-]+)   #capture the guid 
     [ ] 
     \( ([a-zA-Z0-9]+) \) #capture the scheme 
     (?: 
      [ ] 
      ([*])    #capture the star if it exists 
     )? 
    }x; 

next unless match成語說,爲了得到一個不同的線路,如果這一項不匹配正則表達式。 m{regex}/regex/的一般形式。當我在多行中展開正則表達式時,我傾向於使用廣義形式,因爲它使我的編輯器更容易匹配正則表達式的開始和結束。

+1

來選擇結果(在結果中加星標)的方案名稱frm我認爲stack_pointer是EXTINCT欠你幾個小時的工資。 – Ether 2009-09-17 23:40:33

+0

@Ether:我肯定,Chas的幾分鐘時間。如果你是通過stack_pointer去的是EXTINCT的時間,你可能也在那裏。 – ysth 2009-09-18 01:31:55

+0

感謝歐文斯的回答。但有一點我不清楚我是否存儲結果 - > 方案GUID:123-abc(方案1)* 方案GUID:456-def(方案2) 方案GUID:789-ghi(方案3 ) 在長度爲3的數組中...我該如何做代碼?我也明白......「除非我的」聲明有m {<** sumthing **} x; 那是什麼m和x代表?你能幫忙嗎? – 2009-09-18 09:00:23