[英]the regular expression of s/^(.*?):\s*//
在下面的Perl示例中,使用正則表達式,即next unless 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'
]
};
它從第( ^
)行開始到:
匹配,捕獲( (.*?)
)和隨后的任何空格( \\s*
)之間的內容,並將其( s/regex/replacement/
) s/regex/replacement/
為空串。
如果匹配,則返回true值(進行替換的次數),否則返回false。
例如,當$_
為foo: bar
,它將與foo:
匹配並被替換,從而導致$_
為bar
。 之后,第一個捕獲組$1
將包含foo
。
要了解更多信息,請查看:
他們使用了許多人不再使用的舊式快捷方式。 這又是缺少默認變量的代碼。 我也將“ unless
語句反轉為更標准的格式。 也就是說,我將其設為if
語句,並將next
一個語句作為if
塊的一部分:
while ( $_ = <> ) {
if (not $_ =~ s/^(.*?):\s*//) {
next;
}
$HoA{$1} = [ split(/\s+/, $_) ];
}
因此,我們從菱形運算符設置$_
的值。 這基本上是在命令行上獲取文件的名稱,並讀取這些文件中的每一行。 如果命令行上沒有文件,它將從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+/, $_) ];
}
這是從命令行或STDIN上列出的文件中讀取的,並且正在尋找包含冒號的行。 如果該行不包含冒號,它將讀取下一行。
如果一行包含冒號,則從字符串中去除字符串的第一部分,直到第一個冒號,然后再跟隨任何空白。
$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”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.