2011-12-28 194 views

回答

4

它捕獲(並存儲爲$1)一些文本最多:。然後它刪除捕獲的文本,分號和任何尾隨的空格。

超越正則表達式:如果正則表達式成功地完成了它的工作,那麼代碼會使用捕獲的文本作爲其值爲數組引用的散列鍵。該數組的元素是其餘行以空格分隔的行。

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Data::Dumper; 

my %HoA; 

while (<DATA>) { 
    #next unless s/^(.*?):\s*//; 
    next unless 
    s/  #s is replace match operation 
    ^ #start at the beginning of the line 
     ( #begin capture $1 
     .*? #capture anything, but not greedy, i.e. stop before : 
    )  #end capture $1 
     :  #literal colon (must match) 
     \s* #optional whitespace 
    //x; #replace match with nothing, x flag allows formatting and comments 
    $HoA{$1} = [ split ]; 
} 

print Dumper(\%HoA), "\n"; 

__DATA__ 

Thingy: Thing1 Thing2 
Stuff: mystuff yourstuff 
other line that doesn't have a colon 

$VAR1 = { 
      'Thingy' => [ 
         'Thing1', 
         'Thing2' 
         ], 
      'Stuff' => [ 
         'mystuff', 
         'yourstuff' 
        ] 
     }; 
1

它從線(^)的begining匹配,直到一個:,捕捉無論是在((.*?))之間,以及任何後續空間(\s*),並取代它(s/regex/replacement/ )與一個空字符串。

它返回一個真正的值(作出替換的數量),如果匹配,否則爲false。

例如當$_foo: bar,它將匹配foo:和更換,從而導致$_bar。之後,第一個捕獲組$1將包含foo

要了解更多看看:

-1

他們使用了很多舊的快捷方式,大多數人不再使用的。這裏是缺少默認變量的代碼。我還將unless聲明轉換爲更標準的格式。也就是說,我做了一個if語句,並把next作爲if塊的一部分:

while ($_ = <>) { 
    if (not $_ =~ s/^(.*?):\s*//) { 
     next; 
    } 
    $HoA{$1} = [ split(/\s+/, $_) ]; 
} 

因此,我們設定的$_diamond operator值。這基本上採用命令行上文件的名稱並讀取這些文件中的每一行。如果命令行中沒有文件,則從STDIN讀取。

正則表達式更棘手。 ^將正則表達式錨定到行的開頭。否則,正則表達式可以出現在該行的任何地方。例如:

/FOO/ #Will match "FOOBAR" "BARFOOBAR", or "BARFOO" 
/^FOO/ #Will only match "FOOBAR" and not "BARFOOBAR" or "BARFOO" 

.表示任何字符。 *表示前面的零個或多個。因此,.*表示任意數量的字符(包括零個字符。例如:

/^.*:/ #Will match any combination of characters followed by a colon (:). 

因此,這將匹配線:所有的本身(零個或多個),或this is a test:

棘手的部分是其改變在一個非常的*的含義?微妙的方式。通常,正則表達式是貪婪的。他們嘗試匹配他們能最重要的比賽,所以如果你有一個字符串:

my $string = "abc:def:ghij"; 
$string =~ /^.*:/; 

正則表達式匹配它可以在最重要的事情。因此,以上將匹配abc:def:,因爲它是以冒號結尾的最長字符串。通過將?*後,所做的正則表達式作爲非貪婪 - 那就是它將匹配儘可能小的表達。因此:

my $string = "abc:def:ghij"; 
$string =~ /^(.*):/ #Matches "abc:def: 
$string =~ /^(.*?):/ #Matches "abc:" 

\s指任何空白空間,這通常意味着是一個空間或製表符。 *表示零個或多個這些空間。因此,這可能不是空格或多個空格。

my $string = "abc:def: foo"; 
$string =~ /^(.*?):\s*/; #Matches "abc:" 
$string = "abc: This is a test"; 
$string =~ /^(.*?):\s*/; #Matches "abc: " 

現在,s前面的正則表達式意味着替換。基本格式是:

$string =~ s/regex/string/; 

regex是一個正則表達式匹配在$string的東西,而string是更換了比賽。一個簡單的例子是:

$string = "My name is David"; 
$string =~ s/David/Bill/; #String is now "My name is Bill" 

在這種情況下,由正則表達式匹配的字符什麼也沒有被簡單地更換。也就是說,他們是從串中刪除:

$string = "abc: def"; 
$string =~ /^(.*?):\s*/; #$string is now "def". "abc: " has been removed 

所以,多了一個看你的代碼:

while ($_ = <>) { 
    if (not $_ =~ s/^(.*?):\s*//) { 
     next; 
    } 
    $HoA{$1} = [ split(/\s+/, $_) ]; 
} 

這是在命令行上列出的文件中讀取,或從標準輸入,並正在尋找包含冒號的行。如果該行不包含冒號,則會讀取下一行。

如果一行包含冒號,則字符串的第一部分直到第一個冒號,並且任何後續的空白符將從該字符串中剝離。

$1引用在上一個正則表達式的括號內匹配的字符串部分。這是直到第一個冒號的字符串的第一部分。該split極快由空格分隔字符串的剩餘部分,並使其成爲所謂的匿名列表。也就是說,這是創建一個數組哈希(這就是爲什麼這個哈希被稱爲HoA(哈希陣列)。

讓我們給字符串的幾個例子:

____________________________________________________ 
|  STRING  |   RESULTS    | 
|_________________|________________________________| 
| abc: foobar | $HoA{abc} = ["foobar"]   | 
| def:bar fu  | $HoA{def} = ["bar", "fu"]  | 
| ghi:jkl:mno  | $HoA{ghi} = ["jkl:mno"]  | 
| ghi : jkl: mn: | $HoA{"ghi "} = ["jkl:", "mn:"] | 
|_________________|________________________________| 

注意,最後一個將在關鍵的最後一空間。這是「ghi」而不是「ghi」。

+1

真的沒有什麼老舊或者沒有用過隱式使用'$ _',只要它在一個小範圍內(兩行似乎很好)。在這種情況下,它可能沒有多少意思。 '除非'和隱含變量是語言的一部分;如果使用得當,它們是強大而清晰的;不要這麼快就寫下來。進一步使用這樣的'split'使得人們只想查看['perldoc -f split'](http://p3rl.org/split)來查看它的功能! – 2011-12-28 22:42:22

+0

p.s.沒有downvote,時間看起來不好 – 2011-12-28 22:51:50

+0

@JoelBerger - 你說得對,在這種特殊情況下假設使用'$ _'不會影響可讀性,但它並沒有改善它。編程是10%的編碼和90%的維護,'$ _'只是使這個90%的部分更難,這就是爲什麼它被阻止。你沒有完全控制'$ _',所以它可以在你不知道的情況下改變。康威不鼓勵使用_post-fixed_'if if,並且使用'unless'而不是'if'。但是,在這種特殊情況下,他可能會批准固定職位。 – 2011-12-29 15:36:09