在下面的Perl例如,正則表達式被使用,即,next unless s/^(.*?):\s*//;
但是,如何理解這種正則表達式,s/^(.*?):\s*//
S的正則表達式/ ^(*。): S * //
while (<>) {
next unless s/^(.*?):\s*//;
$HoA{$1} = [ split ];
}
在下面的Perl例如,正則表達式被使用,即,next unless s/^(.*?):\s*//;
但是,如何理解這種正則表達式,s/^(.*?):\s*//
S的正則表達式/ ^(*。): S * //
while (<>) {
next unless s/^(.*?):\s*//;
$HoA{$1} = [ split ];
}
它捕獲(並存儲爲$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'
]
};
它從線(^
)的begining匹配,直到一個:
,捕捉無論是在((.*?)
)之間,以及任何後續空間(\s*
),並取代它(s/regex/replacement/
)與一個空字符串。
它返回一個真正的值(作出替換的數量),如果匹配,否則爲false。
例如當$_
是foo: bar
,它將匹配foo:
和更換,從而導致$_
爲bar
。之後,第一個捕獲組$1
將包含foo
。
要了解更多看看:
他們使用了很多舊的快捷方式,大多數人不再使用的。這裏是缺少默認變量的代碼。我還將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」。
真的沒有什麼老舊或者沒有用過隱式使用'$ _',只要它在一個小範圍內(兩行似乎很好)。在這種情況下,它可能沒有多少意思。 '除非'和隱含變量是語言的一部分;如果使用得當,它們是強大而清晰的;不要這麼快就寫下來。進一步使用這樣的'split'使得人們只想查看['perldoc -f split'](http://p3rl.org/split)來查看它的功能! – 2011-12-28 22:42:22
p.s.沒有downvote,時間看起來不好 – 2011-12-28 22:51:50
@JoelBerger - 你說得對,在這種特殊情況下假設使用'$ _'不會影響可讀性,但它並沒有改善它。編程是10%的編碼和90%的維護,'$ _'只是使這個90%的部分更難,這就是爲什麼它被阻止。你沒有完全控制'$ _',所以它可以在你不知道的情況下改變。康威不鼓勵使用_post-fixed_'if if,並且使用'unless'而不是'if'。但是,在這種特殊情況下,他可能會批准固定職位。 – 2011-12-29 15:36:09