正則表達(dá)式

2018-02-24 16:03 更新

正則表達(dá)式比此處所介紹的主題要大得多,確信你理解了這些概念。對(duì)于教程, 可以參閱?perlrequick?或?perlretut。而權(quán)威的文檔,則能夠參閱?perlre

匹配和替換返回?cái)?shù)量

m//?和?s///?操作符分別返回匹配或替換的數(shù)目。你既可以直接使用該數(shù)目, 也可以檢查其真值。

if ( $str =~ /Diggle|Shelley/ ) {
    print "We found Pete or Steve!\n";
}

if ( my $n = ($str =~ s/this/that/g) ) {
    print qq{Replaced $n occurrence(s) of "this"\n};
}

不要在未檢查匹配成功的情況下使用捕獲變量

除非匹配成功,捕獲變量?$1?等是無效的,并且它們不會(huì)被清理。

# BAD: Not checked, but at least it "works".
my $str = 'Perl 101 rocks.';
$str =~ /(\d+)/;
print "Number: $1"; # Prints "Number: 101";

# WORSE: Not checked, and the result is not what you'd expect
$str =~ /(Python|Ruby)/;
print "Language: $1"; # Prints "Language: 101";

你必須檢查匹配的返回值:

# GOOD: Check the results
my $str = 'Perl 101 rocks.';
if ( $str =~ /(\d+)/ ) {
    print "Number: $1"; # Prints "Number: 101";
}

if ( $str =~ /(Python|Ruby)/ ) {
    print "Language: $1"; # Never gets here
}

常用匹配選項(xiàng)

/i:不區(qū)分大小寫

/g:匹配多次

$var = "match match match";

while ($var =~ /match/g) { $a++; }
print "$a\n"; # prints 3

$a = 0;
$a++ foreach ($var =~ /match/g);
print "$a\n"; # prints 3

/m:更改?^?和?$?的意義

正常情況下,^?意為字符串的開頭,而?$?為字符串的結(jié)尾。/m?使它們分別意為行首和行尾。

$str = "one\ntwo\nthree";
@a = $str =~ /^\w+/g;  # @a = ("one");
@b = $str =~ /^\w+/gm; # @b = ("one","two","three")

不管是否有?/m,使用?\A?和?\z?來匹配字符串的開頭和結(jié)尾。\Z?除了會(huì)忽略最后的換行之外,與?\z?相同,

/s:使?.?也匹配換行

$str = "one\ntwo\nthree\n";
$str =~ /^(.{8})/s;
print $1; # prints "one\ntwo\n"

捕獲變量?$1?及之友

捕獲括號(hào)對(duì)的內(nèi)容被存儲(chǔ)到數(shù)字變量中。括號(hào)從左到右分配:

my $str = "abc";
$str =~ /(((a)(b))(c))/;
print "1: $1 2: $2 3: $3 4: $4 5: $5\n";
# prints: 1: abc 2: ab 3: a 4: b 5: c

捕獲括號(hào)及變量的數(shù)目沒有上限。

利用??:?避免捕獲

如果括號(hào)后緊接著??:,那么該分組不會(huì)被捕獲。在你不想保存匹配的內(nèi)容時(shí) 會(huì)有用:

my $str = "abc";
$str =~ /(?:a(b)c)/;
print "$1\n"; # prints "b"

利用?/x?選項(xiàng)使正則表達(dá)式更易讀

如果你在使用正則表達(dá)式時(shí)玩了些花樣,那么為它寫注釋。你可以使用?/x?選項(xiàng)達(dá)到目的。

丑陋的龐然大物:

my ($num) = $ARGV[0] =~ m/^\+?((?:(?<!\+)-)?(?:\d*.)?\d+)$/x;

使用?/x?允許的空白和注釋更可讀:

my ($num) =
    $ARGV[0] =~ m/^ \+?        # An optional plus sign, to be discarded
                (              # Capture...
                (?:(?<!\+)-)?  # a negative sign, if there's no plus behind it,
                (?:\d*.)?      # an optional number, followed by a point if a decimal,
                \d+            # then any number of numbers.
                )$/x;

除非被轉(zhuǎn)義,空白和注釋將被去除。

利用?\Q?和?\E?自動(dòng)引起正則表達(dá)式

這會(huì)自動(dòng)轉(zhuǎn)義正則表達(dá)式的元字符。不會(huì)轉(zhuǎn)義?$?符號(hào)。

my $num = '3.1415';
print "ok 1\n" if $num =~ /\Q3.14\E/;
$num = '3X1415';
print "ok 2\n" if $num =~ /\Q3.14\E/;
print "ok 3\n" if $num =~ /3.14/;

輸出:

ok 1
ok 3

對(duì)?s///?使用?/e?選項(xiàng)來執(zhí)行代碼

這將允許任意代碼替換正則表達(dá)式中的字符串。

my $str = "AbCdE\n";
$str =~ s/(\w)/lc $1/eg;
print $str; # prints "abcde"

必要時(shí)使用?$1?及之友。

了解何時(shí)使用?study

study?在多數(shù)情況下都無用。它所做的是創(chuàng)建一個(gè)每個(gè)單字節(jié)字符首次出現(xiàn)在字符串中 的位置的表。這意味著如果你有 1,000 個(gè)字符長的字符串,你要尋找由一個(gè)常量字符開頭 的各種字符串,匹配器可以立即跳轉(zhuǎn)到正確的位置。例如:

"This is a very long [... 900 characters skipped...] string that I have here,
ending at position 1000"

現(xiàn)在,如果你要匹配正則表達(dá)式?/Icky/,匹配器將試圖尋找第一個(gè)匹配的字母?I。在 找到它之前得掃描前面的 900+ 個(gè)字符。但?study?創(chuàng)建了一個(gè) 256 個(gè)字節(jié)第一次出現(xiàn) 的地方的表。所以掃描器能夠立即跳轉(zhuǎn)到那個(gè)位置來開始匹配。

譯注:這里沒有考慮到多字節(jié)字符。

使用?re => debug?調(diào)試正則表達(dá)式

-Mre=debug
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)